diff --git a/Calorimeter/CaloEvent/CaloEvent/CaloCellClusterWeights.h b/Calorimeter/CaloEvent/CaloEvent/CaloCellClusterWeights.h index b8b0ec8688918b2649a62c32b224a146b1a4b118..956378604ca1d511aa0d93d731faf097deeb7bf6 100644 --- a/Calorimeter/CaloEvent/CaloEvent/CaloCellClusterWeights.h +++ b/Calorimeter/CaloEvent/CaloEvent/CaloCellClusterWeights.h @@ -32,8 +32,6 @@ public: typedef store_t::iterator iterator; ///< @brief Iterator type /// @} - /// @name Constructors - /// @{ /// @brief Default constructor /// /// The constructed data object provides a reserved and sized store appropriate for the total number of cells in the calorimeter. @@ -45,8 +43,8 @@ public: /// /// @param size requested store size CaloCellClusterWeights(size_t size); - /// @} - + /// @brief Copy constructor + CaloCellClusterWeights(const CaloCellClusterWeights& cellClusterWeights); /// @brief Destructor virtual ~CaloCellClusterWeights(); diff --git a/Calorimeter/CaloEvent/src/CaloCellClusterWeights.cxx b/Calorimeter/CaloEvent/src/CaloCellClusterWeights.cxx index 4efe29d829c934c75ae0ada0c873adc514750155..8ea3633c3efb8015809b691da3194cb42b1f877e 100644 --- a/Calorimeter/CaloEvent/src/CaloCellClusterWeights.cxx +++ b/Calorimeter/CaloEvent/src/CaloCellClusterWeights.cxx @@ -21,6 +21,10 @@ CaloCellClusterWeights::CaloCellClusterWeights() : CaloCellClusterWeights( CELLCLUSTERLOOKUP ) { } +CaloCellClusterWeights::CaloCellClusterWeights(const CaloCellClusterWeights& cellClusterWeights) + : _hashTable(cellClusterWeights._hashTable) +{ } + CaloCellClusterWeights::~CaloCellClusterWeights() { } diff --git a/Calorimeter/CaloExample/CaloRecEx/share/CaloRecOutputItemList_jobOptions.py b/Calorimeter/CaloExample/CaloRecEx/share/CaloRecOutputItemList_jobOptions.py index 6d7041f7d903aa99217a21eb90999f15029e6d73..ac1be5c7246b363a033773abcddadbefeea7ea0a 100644 --- a/Calorimeter/CaloExample/CaloRecEx/share/CaloRecOutputItemList_jobOptions.py +++ b/Calorimeter/CaloExample/CaloRecEx/share/CaloRecOutputItemList_jobOptions.py @@ -7,10 +7,6 @@ CaloESDList = [] CaloESDList += [ "CaloCellContainer#AllCalo" ] -# compactify calo cell -from CaloTools.CaloToolsConf import CaloCompactCellTool -svcMgr.ToolSvc += CaloCompactCellTool() - # add explicitly E4', MBTS cells and trigger output to ESD CaloESDList += [ "TileCellContainer#E4prContainer" ] CaloESDList += [ "TileCellContainer#MBTSContainer" ] @@ -21,6 +17,11 @@ CaloClusterItemList=[] CaloClusterKeys=[] CaloClusterKeys+=["CaloCalTopoClusters"] +if jobproperties.CaloRecFlags.doCaloTopoTower.get_Value(): + CaloClusterKeys+=["CaloCalTopoTowers"] +if jobproperties.CaloRecFlags.doCaloTopoSignal.get_Value(): + CaloClusterKeys+=["CaloCalTopoSignals"] +##CaloClusterKeys+=["CaloCalFwdTopoTowers"] CaloClusterKeys+=["CombinedCluster"] #CaloClusterKeys+=["EMTopoCluster430"] CaloClusterKeys+=["EMTopoSW35"] @@ -84,9 +85,9 @@ if jobproperties.Beam.beamType() == 'cosmics' or jobproperties.Beam.beamType() = #List of AOD moments: (copied from CaloClusterTopoGetter) -AODMoments=[#"LATERAL" +AODMoments=["SECOND_R" + #,"LATERAL" #,"LONGITUDINAL" - "SECOND_R" ,"SECOND_LAMBDA" ,"CENTER_MAG" ,"CENTER_LAMBDA" @@ -107,36 +108,55 @@ AODMoments=[#"LATERAL" ,"EM_PROBABILITY" #,"PTD" ,"BadChannelList" - ,#"LATERAL" + #,"MASS" ] + +if jobproperties.CaloRecFlags.doExtendedClusterMoments.get_Value(): + AODMoments += ["LATERAL" + ,"ENG_BAD_HV_CELLS" + ,"N_BAD_HV_CELLS" + ,"SIGNIFICANCE" + ,"CELL_SIGNIFICANCE" + ,"CELL_SIG_SAMPLING" + ,"PTD" + ,"MASS" + ] try: from Digitization.DigitizationFlags import digitizationFlags if digitizationFlags.doDigiTruth(): - AODMoments+=["SECOND_R_DigiHSTruth" - ,"SECOND_LAMBDA_DigiHSTruth" - ,"CENTER_MAG_DigiHSTruth" - ,"CENTER_LAMBDA_DigiHSTruth" - ,"FIRST_ENG_DENS_DigiHSTruth" - ,"ENG_FRAC_MAX_DigiHSTruth" - ,"ISOLATION_DigiHSTruth" - ,"ENG_BAD_CELLS_DigiHSTruth" - ,"N_BAD_CELLS_DigiHSTruth" - ,"BADLARQ_FRAC_DigiHSTruth" - #,"ENG_BAD_HV_CELLS_Truth" - #,"N_BAD_HV_CELLS_Truth" - ,"ENG_POS_DigiHSTruth" - #,"SIGNIFICANCE_Truth" - #,"CELL_SIGNIFICANCE_Truth" - #,"CELL_SIG_SAMPLING_Truth" - ,"AVG_LAR_Q_DigiHSTruth" - ,"AVG_TILE_Q_DigiHSTruth" - ,"EM_PROBABILITY_DigiHSTruth" - #,"PTD_Truth" - ,"ENERGY_DigiHSTruth" - ,"ETA_DigiHSTruth" - ,"PHI_DigiHSTruth" - ] + AODMoments+=["SECOND_R_DigiHSTruth" + ,"SECOND_LAMBDA_DigiHSTruth" + ,"CENTER_MAG_DigiHSTruth" + ,"CENTER_LAMBDA_DigiHSTruth" + ,"FIRST_ENG_DENS_DigiHSTruth" + ,"ENG_FRAC_MAX_DigiHSTruth" + ,"ISOLATION_DigiHSTruth" + ,"ENG_BAD_CELLS_DigiHSTruth" + ,"N_BAD_CELLS_DigiHSTruth" + ,"BADLARQ_FRAC_DigiHSTruth" + #,"ENG_BAD_HV_CELLS_Truth" + #,"N_BAD_HV_CELLS_Truth" + ,"ENG_POS_DigiHSTruth" + #,"SIGNIFICANCE_Truth" + #,"CELL_SIGNIFICANCE_Truth" + #,"CELL_SIG_SAMPLING_Truth" + ,"AVG_LAR_Q_DigiHSTruth" + ,"AVG_TILE_Q_DigiHSTruth" + ,"EM_PROBABILITY_DigiHSTruth" + #,"PTD_Truth" + ,"ENERGY_DigiHSTruth" + ,"ETA_DigiHSTruth" + ,"PHI_DigiHSTruth" + ] + if jobproperties.CaloRecFlags.doExtendedClusterMoments.get_Value(): + AODMoments+=["ENG_BAD_HV_CELLS_Truth" + ,"N_BAD_HV_CELLS_Truth" + ,"SIGNIFICANCE_Truth" + ,"CELL_SIGNIFICANCE_Truth" + ,"CELL_SIG_SAMPLING_Truth" + ,"PTD_Truth" + ] except: log = logging.getLogger('CaloRecOutputItemList') log.info('Unable to import DigitizationFlags in CaloRecOutputItemList_jobOptions. Expected in AthenaP1') @@ -153,6 +173,11 @@ CaloClusterKeys=[] CaloClusterKeys+=["CaloCalTopoClusters"] +if jobproperties.CaloRecFlags.doCaloTopoTower.get_Value(): + CaloClusterKeys+=["CaloCalTopoTowers"] +if jobproperties.CaloRecFlags.doCaloTopoSignal.get_Value(): + CaloClusterKeys+=["CaloCalTopoSignals"] +##CaloClusterKeys+=["CaloCalFwdTopoTowers"] CaloClusterKeys+=["CombinedCluster"] #CaloClusterKeys+=["EMTopoCluster430"] CaloClusterKeys+=["EMTopoSW35"] diff --git a/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerCalibrator.h b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerCalibrator.h index 52c5a21cb3ef285d77b32495b26ed130d68d722b..dd6b13bbedfea55d726448bea8c313e4da91f955 100644 --- a/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerCalibrator.h +++ b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerCalibrator.h @@ -3,6 +3,8 @@ #ifndef CALOREC_CALOTOPOCLUSTERFROMTOWERCALIBRATOR_H #define CALOREC_CALOTOPOCLUSTERFROMTOWERCALIBRATOR_H +#include "StoreGate/ReadHandleKey.h" + #include "AthenaBaseComps/AthAlgTool.h" #include "CaloRec/CaloClusterCollectionProcessor.h" @@ -18,6 +20,9 @@ public: /// @brief Tool constructor CaloTopoClusterFromTowerCalibrator(const std::string& type,const std::string& name,const IInterface* pParent); + /// @brief Tool initialization + StatusCode initialize(); + /// @brief Tool execution StatusCode execute(xAOD::CaloClusterContainer* pClusCont); @@ -25,16 +30,20 @@ private: /// @name Tool properties /// @{ - std::string m_cellClusterWeightsKey; ///> @brief Key for cell-cluster weight look up object - bool m_orderByPt; ///> @brief Turn on pT ordering + SG::ReadHandleKey<CaloCellClusterWeights> m_cellClusterWeightKey; ///< Key for handle to cell-cluster weight look up object + bool m_orderByPt; ///< Turn on pT ordering if @c true /// @} - - /// @brief Default container key - static std::string m_defaultKey; }; /// @class CaloTopoClusterFromTowerCalibrator /// -/// @brief A cluster builder tool calibrated topo-clusters formed from calorimeter towers to the LCW scale. +/// @brief A cluster builder tool to calibrate topo-clusters formed from (EM) calorimeter towers to the LCW scale. /// +/// This module applies LCW weights to cells contributing to towers represented by @c xAOD::CaloCluster objects. +/// The overall energy contribution of a given cell contributing to a given tower is then @f$ w_{\rm geo} \times w_{\rm LCW} \times E_{\rm cell} @f$, +/// where @f$ w_{\rm geo} @f$ is the geometrical weight, @f$ w_{\rm LCW} @f$ is +/// the calibration weight the cell received from the LCW calibration in the context of the @c xAOD::CaloCluster objects it contributes to (at most two), +/// and @f$ E_{\rm cell} @f$ is the cell energy on EM scale. More details on the weights are given on +/// <a href="https://twiki.cern.ch/twiki/bin/view/AtlasSandboxProtected/CaloTowerPerformance" title="https://twiki.cern.ch/twiki/bin/view/AtlasSandboxProtected/CaloTowerPerformance">this page</a>. +/// /// @author Peter Loch <loch@physics.arizona.edu> #endif diff --git a/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerHelpers.h b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerHelpers.h index bf56e0146012d557a9dacfc7078d4dd5d3f3df8a..797de7a586b8ec3570d9c301d7204e6b3b413193 100644 --- a/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerHelpers.h +++ b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerHelpers.h @@ -8,6 +8,14 @@ #include "xAODCaloEvent/CaloCluster.h" #include <cstdarg> +#include <string> +#include <map> + +#define _SNAMELU( NAME ) { CaloSampling::NAME , std::string( #NAME ) } +#define _SIDLU( ID ) { std::string( #ID ) , CaloSampling::ID } + +#define _MNAMELU( NAME ) { xAOD::CaloCluster::NAME, std::string( #NAME ) } +#define _MIDLU( ID ) { std::string( #ID ) , xAOD::CaloCluster::ID } class CaloCell; @@ -147,5 +155,117 @@ namespace CaloRec { bool calculateKine(xAOD::CaloCluster* pClus,bool onlyKine=false); /// @} } // Helpers + + ///@brief Stores + namespace Lookup { + ///@name Sampling names and identifier maps + ///@{ + static const std::map<CaloSampling::CaloSample,std::string> samplingNames = { + // EM + _SNAMELU( PreSamplerB ), _SNAMELU( EMB1 ), _SNAMELU( EMB2 ), _SNAMELU( EMB3 ), + _SNAMELU( PreSamplerE ), _SNAMELU( EME1 ), _SNAMELU( EME2 ), _SNAMELU( EME3 ), + // HAD + _SNAMELU( HEC0 ), _SNAMELU( HEC1 ), _SNAMELU( HEC2 ), _SNAMELU( HEC3 ), + _SNAMELU( TileBar0 ), _SNAMELU( TileBar1 ), _SNAMELU( TileBar2 ), + // Tile + _SNAMELU( TileBar0 ), _SNAMELU( TileBar1 ), _SNAMELU( TileBar2 ), + _SNAMELU( TileGap1 ), _SNAMELU( TileGap2 ), _SNAMELU( TileGap3 ), + _SNAMELU( TileExt0 ), _SNAMELU( TileExt1 ), _SNAMELU( TileExt2 ), + // FCal + _SNAMELU( FCAL0 ), _SNAMELU( FCAL1 ), _SNAMELU( FCAL2 ), + // Mini-FCal + _SNAMELU( MINIFCAL0 ), _SNAMELU( MINIFCAL1 ), _SNAMELU( MINIFCAL2 ), _SNAMELU( MINIFCAL3 ), + // unknown + _SNAMELU( Unknown ) + }; ///< Name lookup by sampling identifier (data) + static const std::map<std::string,CaloSampling::CaloSample> samplingIds = { + // EM + _SIDLU( PreSamplerB ), _SIDLU( EMB1 ), _SIDLU( EMB2 ), _SIDLU( EMB3 ), + _SIDLU( PreSamplerE ), _SIDLU( EME1 ), _SIDLU( EME2 ), _SIDLU( EME3 ), + // HAD + _SIDLU( HEC0 ), _SIDLU( HEC1 ), _SIDLU( HEC2 ), _SIDLU( HEC3 ), + _SIDLU( TileBar0 ), _SIDLU( TileBar1 ), _SIDLU( TileBar2 ), + // Tile + _SIDLU( TileBar0 ), _SIDLU( TileBar1 ), _SIDLU( TileBar2 ), + _SIDLU( TileGap1 ), _SIDLU( TileGap2 ), _SIDLU( TileGap3 ), + _SIDLU( TileExt0 ), _SIDLU( TileExt1 ), _SIDLU( TileExt2 ), + // FCal + _SIDLU( FCAL0 ), _SIDLU( FCAL1 ), _SIDLU( FCAL2 ), + // Mini-FCal + _SIDLU( MINIFCAL0 ), _SIDLU( MINIFCAL1 ), _SIDLU( MINIFCAL2 ), _SIDLU( MINIFCAL3 ), + // unknown + _SIDLU( Unknown ) + }; ///< Identifier lookup by sampling name (data) + static const std::string& getSamplingName(CaloSampling::CaloSample sid); ///< Lookup sampling name by identifier (function) + static CaloSampling::CaloSample getSamplingId(const std::string& sname); ///< Lookup sampling identifier by name (function) + ///@} + ///@name Cluster moment names and identifier maps + ///@{ + static const std::map<xAOD::CaloCluster::MomentType,std::string> clusterMomentNames = { + _MNAMELU( FIRST_PHI ),_MNAMELU( FIRST_ETA ),_MNAMELU( SECOND_R ),_MNAMELU( SECOND_LAMBDA ),_MNAMELU( DELTA_PHI ),_MNAMELU( DELTA_THETA ),_MNAMELU( DELTA_ALPHA ), + _MNAMELU( CENTER_X ),_MNAMELU( CENTER_Y ),_MNAMELU( CENTER_Z ),_MNAMELU( CENTER_MAG ),_MNAMELU( CENTER_LAMBDA ),_MNAMELU( LATERAL ),_MNAMELU( LONGITUDINAL ), + _MNAMELU( ENG_FRAC_EM ),_MNAMELU( ENG_FRAC_MAX ),_MNAMELU( ENG_FRAC_CORE ),_MNAMELU( FIRST_ENG_DENS ),_MNAMELU( SECOND_ENG_DENS ),_MNAMELU( ENG_POS ), + _MNAMELU( ISOLATION ),_MNAMELU( ENG_BAD_CELLS ),_MNAMELU( N_BAD_CELLS ),_MNAMELU( N_BAD_CELLS_CORR ),_MNAMELU( BAD_CELLS_CORR_E ),_MNAMELU( BADLARQ_FRAC ), + _MNAMELU( SIGNIFICANCE ),_MNAMELU( CELL_SIGNIFICANCE ),_MNAMELU( CELL_SIG_SAMPLING ),_MNAMELU( AVG_LAR_Q ),_MNAMELU( AVG_TILE_Q ),_MNAMELU( ENG_BAD_HV_CELLS ), + _MNAMELU( N_BAD_HV_CELLS ),_MNAMELU( PTD ),_MNAMELU( MASS ),_MNAMELU( EM_PROBABILITY ),_MNAMELU( HAD_WEIGHT ),_MNAMELU( OOC_WEIGHT ),_MNAMELU( DM_WEIGHT ), + _MNAMELU( TILE_CONFIDENCE_LEVEL ),_MNAMELU( VERTEX_FRACTION ),_MNAMELU( NVERTEX_FRACTION ),_MNAMELU( ETACALOFRAME ),_MNAMELU( PHICALOFRAME ),_MNAMELU( ETA1CALOFRAME ), + _MNAMELU( PHI1CALOFRAME ),_MNAMELU( ETA2CALOFRAME ),_MNAMELU( PHI2CALOFRAME ),_MNAMELU( ENG_CALIB_TOT ),_MNAMELU( ENG_CALIB_OUT_L ),_MNAMELU( ENG_CALIB_OUT_M ), + _MNAMELU( ENG_CALIB_OUT_T ),_MNAMELU( ENG_CALIB_DEAD_L ),_MNAMELU( ENG_CALIB_DEAD_M ),_MNAMELU( ENG_CALIB_DEAD_T ),_MNAMELU( ENG_CALIB_EMB0 ),_MNAMELU( ENG_CALIB_EME0 ), + _MNAMELU( ENG_CALIB_TILEG3 ),_MNAMELU( ENG_CALIB_DEAD_TOT ),_MNAMELU( ENG_CALIB_DEAD_EMB0 ),_MNAMELU( ENG_CALIB_DEAD_TILE0 ),_MNAMELU( ENG_CALIB_DEAD_TILEG3 ), + _MNAMELU( ENG_CALIB_DEAD_EME0 ),_MNAMELU( ENG_CALIB_DEAD_HEC0 ),_MNAMELU( ENG_CALIB_DEAD_FCAL ),_MNAMELU( ENG_CALIB_DEAD_LEAKAGE ),_MNAMELU( ENG_CALIB_DEAD_UNCLASS ), + _MNAMELU( ENG_CALIB_FRAC_EM ),_MNAMELU( ENG_CALIB_FRAC_HAD ),_MNAMELU( ENG_CALIB_FRAC_REST ),_MNAMELU( ENERGY_DigiHSTruth ),_MNAMELU( ETA_DigiHSTruth ),_MNAMELU( PHI_DigiHSTruth ), + _MNAMELU( TIME_DigiHSTruth ),_MNAMELU( ENERGY_CALIB_DigiHSTruth ),_MNAMELU( ETA_CALIB_DigiHSTruth ),_MNAMELU( PHI_CALIB_DigiHSTruth ),_MNAMELU( TIME_CALIB_DigiHSTruth ), + _MNAMELU( FIRST_PHI_DigiHSTruth ),_MNAMELU( FIRST_ETA_DigiHSTruth ),_MNAMELU( SECOND_R_DigiHSTruth ),_MNAMELU( SECOND_LAMBDA_DigiHSTruth ),_MNAMELU( DELTA_PHI_DigiHSTruth ), + _MNAMELU( DELTA_THETA_DigiHSTruth ),_MNAMELU( DELTA_ALPHA_DigiHSTruth ),_MNAMELU( CENTER_X_DigiHSTruth ),_MNAMELU( CENTER_Y_DigiHSTruth ),_MNAMELU( CENTER_Z_DigiHSTruth ), + _MNAMELU( CENTER_MAG_DigiHSTruth ),_MNAMELU( CENTER_LAMBDA_DigiHSTruth ),_MNAMELU( LATERAL_DigiHSTruth ),_MNAMELU( LONGITUDINAL_DigiHSTruth ),_MNAMELU( ENG_FRAC_EM_DigiHSTruth ), + _MNAMELU( ENG_FRAC_MAX_DigiHSTruth ),_MNAMELU( ENG_FRAC_CORE_DigiHSTruth ),_MNAMELU( FIRST_ENG_DENS_DigiHSTruth ),_MNAMELU( SECOND_ENG_DENS_DigiHSTruth ), + _MNAMELU( ISOLATION_DigiHSTruth ),_MNAMELU( ENG_BAD_CELLS_DigiHSTruth ),_MNAMELU( N_BAD_CELLS_DigiHSTruth ),_MNAMELU( N_BAD_CELLS_CORR_DigiHSTruth ), + _MNAMELU( BAD_CELLS_CORR_E_DigiHSTruth ),_MNAMELU( BADLARQ_FRAC_DigiHSTruth ),_MNAMELU( ENG_POS_DigiHSTruth ),_MNAMELU( SIGNIFICANCE_DigiHSTruth ), + _MNAMELU( CELL_SIGNIFICANCE_DigiHSTruth ),_MNAMELU( CELL_SIG_SAMPLING_DigiHSTruth ),_MNAMELU( AVG_LAR_Q_DigiHSTruth ),_MNAMELU( AVG_TILE_Q_DigiHSTruth ), + _MNAMELU( ENG_BAD_HV_CELLS_DigiHSTruth ),_MNAMELU( N_BAD_HV_CELLS_DigiHSTruth ),_MNAMELU( EM_PROBABILITY_DigiHSTruth ),_MNAMELU( HAD_WEIGHT_DigiHSTruth ), + _MNAMELU( OOC_WEIGHT_DigiHSTruth ),_MNAMELU( DM_WEIGHT_DigiHSTruth ) + }; ///< Moment names by moment types + static const std::map<std::string,xAOD::CaloCluster::MomentType> clusterMomentTypes = { + _MIDLU( FIRST_PHI ),_MIDLU( FIRST_ETA ),_MIDLU( SECOND_R ),_MIDLU( SECOND_LAMBDA ),_MIDLU( DELTA_PHI ),_MIDLU( DELTA_THETA ),_MIDLU( DELTA_ALPHA ), + _MIDLU( CENTER_X ),_MIDLU( CENTER_Y ),_MIDLU( CENTER_Z ),_MIDLU( CENTER_MAG ),_MIDLU( CENTER_LAMBDA ),_MIDLU( LATERAL ),_MIDLU( LONGITUDINAL ), + _MIDLU( ENG_FRAC_EM ),_MIDLU( ENG_FRAC_MAX ),_MIDLU( ENG_FRAC_CORE ),_MIDLU( FIRST_ENG_DENS ),_MIDLU( SECOND_ENG_DENS ),_MIDLU( ENG_POS ), + _MIDLU( ISOLATION ),_MIDLU( ENG_BAD_CELLS ),_MIDLU( N_BAD_CELLS ),_MIDLU( N_BAD_CELLS_CORR ),_MIDLU( BAD_CELLS_CORR_E ),_MIDLU( BADLARQ_FRAC ), + _MIDLU( SIGNIFICANCE ),_MIDLU( CELL_SIGNIFICANCE ),_MIDLU( CELL_SIG_SAMPLING ),_MIDLU( AVG_LAR_Q ),_MIDLU( AVG_TILE_Q ),_MIDLU( ENG_BAD_HV_CELLS ), + _MIDLU( N_BAD_HV_CELLS ),_MIDLU( PTD ),_MIDLU( MASS ),_MIDLU( EM_PROBABILITY ),_MIDLU( HAD_WEIGHT ),_MIDLU( OOC_WEIGHT ),_MIDLU( DM_WEIGHT ), + _MIDLU( TILE_CONFIDENCE_LEVEL ),_MIDLU( VERTEX_FRACTION ),_MIDLU( NVERTEX_FRACTION ),_MIDLU( ETACALOFRAME ),_MIDLU( PHICALOFRAME ),_MIDLU( ETA1CALOFRAME ), + _MIDLU( PHI1CALOFRAME ),_MIDLU( ETA2CALOFRAME ),_MIDLU( PHI2CALOFRAME ),_MIDLU( ENG_CALIB_TOT ),_MIDLU( ENG_CALIB_OUT_L ),_MIDLU( ENG_CALIB_OUT_M ), + _MIDLU( ENG_CALIB_OUT_T ),_MIDLU( ENG_CALIB_DEAD_L ),_MIDLU( ENG_CALIB_DEAD_M ),_MIDLU( ENG_CALIB_DEAD_T ),_MIDLU( ENG_CALIB_EMB0 ),_MIDLU( ENG_CALIB_EME0 ), + _MIDLU( ENG_CALIB_TILEG3 ),_MIDLU( ENG_CALIB_DEAD_TOT ),_MIDLU( ENG_CALIB_DEAD_EMB0 ),_MIDLU( ENG_CALIB_DEAD_TILE0 ),_MIDLU( ENG_CALIB_DEAD_TILEG3 ), + _MIDLU( ENG_CALIB_DEAD_EME0 ),_MIDLU( ENG_CALIB_DEAD_HEC0 ),_MIDLU( ENG_CALIB_DEAD_FCAL ),_MIDLU( ENG_CALIB_DEAD_LEAKAGE ),_MIDLU( ENG_CALIB_DEAD_UNCLASS ), + _MIDLU( ENG_CALIB_FRAC_EM ),_MIDLU( ENG_CALIB_FRAC_HAD ),_MIDLU( ENG_CALIB_FRAC_REST ),_MIDLU( ENERGY_DigiHSTruth ),_MIDLU( ETA_DigiHSTruth ),_MIDLU( PHI_DigiHSTruth ), + _MIDLU( TIME_DigiHSTruth ),_MIDLU( ENERGY_CALIB_DigiHSTruth ),_MIDLU( ETA_CALIB_DigiHSTruth ),_MIDLU( PHI_CALIB_DigiHSTruth ),_MIDLU( TIME_CALIB_DigiHSTruth ), + _MIDLU( FIRST_PHI_DigiHSTruth ),_MIDLU( FIRST_ETA_DigiHSTruth ),_MIDLU( SECOND_R_DigiHSTruth ),_MIDLU( SECOND_LAMBDA_DigiHSTruth ),_MIDLU( DELTA_PHI_DigiHSTruth ), + _MIDLU( DELTA_THETA_DigiHSTruth ),_MIDLU( DELTA_ALPHA_DigiHSTruth ),_MIDLU( CENTER_X_DigiHSTruth ),_MIDLU( CENTER_Y_DigiHSTruth ),_MIDLU( CENTER_Z_DigiHSTruth ), + _MIDLU( CENTER_MAG_DigiHSTruth ),_MIDLU( CENTER_LAMBDA_DigiHSTruth ),_MIDLU( LATERAL_DigiHSTruth ),_MIDLU( LONGITUDINAL_DigiHSTruth ),_MIDLU( ENG_FRAC_EM_DigiHSTruth ), + _MIDLU( ENG_FRAC_MAX_DigiHSTruth ),_MIDLU( ENG_FRAC_CORE_DigiHSTruth ),_MIDLU( FIRST_ENG_DENS_DigiHSTruth ),_MIDLU( SECOND_ENG_DENS_DigiHSTruth ), + _MIDLU( ISOLATION_DigiHSTruth ),_MIDLU( ENG_BAD_CELLS_DigiHSTruth ),_MIDLU( N_BAD_CELLS_DigiHSTruth ),_MIDLU( N_BAD_CELLS_CORR_DigiHSTruth ), + _MIDLU( BAD_CELLS_CORR_E_DigiHSTruth ),_MIDLU( BADLARQ_FRAC_DigiHSTruth ),_MIDLU( ENG_POS_DigiHSTruth ),_MIDLU( SIGNIFICANCE_DigiHSTruth ), + _MIDLU( CELL_SIGNIFICANCE_DigiHSTruth ),_MIDLU( CELL_SIG_SAMPLING_DigiHSTruth ),_MIDLU( AVG_LAR_Q_DigiHSTruth ),_MIDLU( AVG_TILE_Q_DigiHSTruth ), + _MIDLU( ENG_BAD_HV_CELLS_DigiHSTruth ),_MIDLU( N_BAD_HV_CELLS_DigiHSTruth ),_MIDLU( EM_PROBABILITY_DigiHSTruth ),_MIDLU( HAD_WEIGHT_DigiHSTruth ), + _MIDLU( OOC_WEIGHT_DigiHSTruth ),_MIDLU( DM_WEIGHT_DigiHSTruth ) + }; ///< Moment names buy moment identifiers + static const std::string& getMomentName(xAOD::CaloCluster::MomentType momentType); ///< Get moment name associated with a moment type + static bool getMomentType(const std::string& momentName,xAOD::CaloCluster::MomentType& momentType); ///< Get moment type associated with a moment name + static bool haveMomentType(const std::string& momentName); ///< Returns @c true in case moment is known + ///@} + } // Lookup } // CaloRec + +inline const std::string& CaloRec::Lookup::getSamplingName(CaloSampling::CaloSample sid) { return samplingNames.find(sid)->second; } +inline CaloSampling::CaloSample CaloRec::Lookup::getSamplingId(const std::string& sname) { + auto fid(samplingIds.find(sname)); return fid != samplingIds.end() ? fid->second : samplingIds.find("Unknown")->second; +} + +inline bool CaloRec::Lookup::haveMomentType(const std::string& momentName) { return clusterMomentTypes.find(momentName) != clusterMomentTypes.end(); } +inline const std::string& CaloRec::Lookup::getMomentName(xAOD::CaloCluster::MomentType momentType) { return clusterMomentNames.at(momentType); } +inline bool CaloRec::Lookup::getMomentType(const std::string& momentName,xAOD::CaloCluster::MomentType& momentType) { + bool isOk(haveMomentType(momentName)); if ( isOk ) { momentType = clusterMomentTypes.at(momentName); } return isOk; +} + + #endif diff --git a/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerMaker.h b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerMaker.h index c9f493dc982eecdde5c04799d4b8c76f71f05c1b..858bb1dfbcda02d2b2e01266c6e828fc3aa0fdab 100644 --- a/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerMaker.h +++ b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerMaker.h @@ -1,248 +1,254 @@ // -*- c++ -*- -/* Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration */ +/* Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ #ifndef CALOREC_CALOTOPOCLUSTERFROMTOWERMAKER_H #define CALOREC_CALOTOPOCLUSTERFROMTOWERMAKER_H -#include "AthenaBaseComps/AthAlgTool.h" +#include "StoreGate/ReadHandleKey.h" +#include "StoreGate/WriteHandleKey.h" + +#include "GaudiKernel/ServiceHandle.h" -#include "CaloEvent/CaloCellTowerLink.h" +#include "AthenaBaseComps/AthAlgTool.h" #include "CaloRec/CaloClusterCollectionProcessor.h" +#include "CaloRec/CaloTowerGeometrySvc.h" #include "CaloRec/CaloProtoCluster.h" +#include "CaloEvent/CaloCell.h" +#include "CaloEvent/CaloClusterCellLink.h" +#include "CaloEvent/CaloCellClusterWeights.h" +#include "CaloEvent/CaloCellContainer.h" + +#include "CaloGeoHelpers/CaloSampling.h" + #include "xAODCaloEvent/CaloClusterContainer.h" -#include "xAODCaloEvent/CaloTowerContainer.h" #include <string> -#include <map> - #include <vector> -#include <boost/tuple/tuple.hpp> +#include <bitset> +#include <map> -class CaloClusterCellLink; -class CaloCell; -class CaloCellClusterWeights; +#ifndef _CALOTOPOCLUSTERFROMTOWERMAKER_BITSET_SIZE +#define _CALOTOPOCLUSTERFROMTOWERMAKER_BITSET_SIZE 28 +#endif class CaloTopoClusterFromTowerMaker : public AthAlgTool, virtual public CaloClusterCollectionProcessor { public: - /// @brief Tool constructor + ///@brief Tool constructor CaloTopoClusterFromTowerMaker(const std::string& type,const std::string& name,const IInterface* pParent); - /// @brief Tool initialization - StatusCode initialize(); - - /// @brief Tool execution - StatusCode execute(xAOD::CaloClusterContainer* pClusCont); - - /// @brief Tool finalize - StatusCode finalize(); + ///@name @c AthAlgTool and @c CaloClusterCellProcessor interface implementations + ///@{ + StatusCode initialize(); ///< Setting up the operational mode and corresponding parameters + StatusCode execute(xAOD::CaloClusterContainer* pClusCont); ///< Execute the tool and fill the @c xAOD::CaloClusterContainer pointed to by @c pClusCont + StatusCode finalize(); ///< Finalize the tool (no action) + ///@} private: - /// @name Tool properties - /// @{ - std::string m_towerContainerKey; ///> @brief Key (name) of input tower container - std::string m_cellTowerLinksKey; ///> @brief Derived property (cannot be set by user) - std::string m_cellContainerKey; ///> @brief Key (name) of input cell container - std::string m_clusterContainerKey; ///> @brief Key of topo-cluster container to be used as source for cells - std::string m_cellClusterWeightKey; ///> @brief Key for cell-cluster weight look up object - bool m_orderByPt; ///> @brief Orders cluster container by @f$ p_{\text{T}} @f$, default @c true - double m_energyThreshold; ///> @brief Cell energy threshold - bool m_applyLCW; ///> @brief Prepare LCW calibration - /// @} + ///@name Internally used types + ///@{ + typedef std::vector<CaloProtoCluster> protocont_t; ///< Container for @c CaloProtoCluster objects + typedef std::size_t uint_t; ///< Unsigned integral type + ///@} - /// @name Processing flags + /// @name Tool properties /// @{ - /// @brief Energy threshold flag - bool m_applyEnergyThreshold; - /// @brief Use cells from topo-clusters flag - bool m_useCellsFromClusters; - /// @brief Prepare LCW calibration - bool m_prepareLCW; + ServiceHandle<CaloTowerGeometrySvc> m_towerGeometrySvc; ///< Tower geometry service + SG::ReadHandleKey<xAOD::CaloClusterContainer> m_clusterContainerKey; ///< Topo-cluster container key + SG::ReadHandleKey<CaloCellContainer> m_cellContainerKey; ///< Calorimeter cell container + SG::WriteHandleKey<CaloCellClusterWeights> m_cellClusterWeightKey; ///< Cell signal weights in clusters key + bool m_orderByPt; ///< Orders cluster container by @f$ p_{\text{T}} @f$, default @c true + bool m_prepareLCW; ///< Prepare LCW calibration, default is @c false + bool m_useCellsFromClusters; ///< Use cells from topo-clusters if @c true, else use all cells, default is @c true + bool m_applyCellEnergyThreshold; ///< Apply cell energy threshold, default is @c false + bool m_doCellIndexCheck; ///< Check cell hash index consistency if @c true (default @c false) + bool m_buildCombinedSignal; ///< 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> /// @} /// @name Constants and parameters /// @{ - /// @brief Number of cells - int m_numberOfCells; - /// @brief Number of samplings - int m_numberOfSamplings; - /// @brief Default energy threshold - static double m_energyThresholdDef; - /// @brief Default container key - static std::string m_defaultKey; + uint_t m_numberOfCells; ///< Number of cells (highest cell index + 1) + uint_t m_maxCellHash; ///< Maximum hash index of cell ( number of cells - 1) + uint_t m_numberOfSamplings; ///< Number of samplings + uint_t m_numberOfTowers; ///< Number of towers + static double m_energyThresholdDef; ///< Default energy threshold + static double m_clusterRangeDef; ///< Default cluster @f$ y @f$ range + static std::string m_defaultKey; ///< Default container key + static uint_t m_errorValueUINT; ///< Error value for @c uint_t type values /// @} - /// @brief Access to cell-to-tower links - const CaloCellTowerLink::Map* m_cellTowerLinksHandle; - - /// @name Cache for cell weights - /// @{ - /// @brief Data structure tagging a cell as a cluster cell and storing its weight - typedef boost::tuples::tuple<bool,double> celltag_t; - /// @brief Random access lookup of cell tags - typedef std::vector<celltag_t> celltagstore_t; - /// @brief Cell tag store - celltagstore_t m_cellTagStore; - /// @brief Previously used cell indices - std::vector<size_t> m_cellIdxStore; - /// @} + ///@name Internally used helpers + ///@{ + xAOD::CaloCluster::ClusterSize getClusterSize(uint_t etaBins,uint_t phiBins); ///< Returns a cluster size tag from number of eta and phi bins in tower grid + xAOD::CaloCluster::ClusterSize getClusterSize(uint_t towerBins); ///< Returns a cluster size tag from number of towers (bins) in tower grid + int cleanupCells(CaloClusterCellLink* clk,uint_t nclus); ///< Checks @c CaloClusterCellLink for consistency + ///@} - /// @brief Pathologies - /// - /// Internally used object collects pathologies observed for @c CaloCell objects in execution. - /// Each pathology is identified by a pre-defined message, and the number of pathologies is produced by - /// counting the number of occurancies of a given message. - class CellPathology - { - public: - /// @name Internally used data types - /// @{ - typedef std::string pathology_t; - typedef int count_t; - typedef std::map<pathology_t,count_t> cache_t; - /// @} - - /// @brief Constructor - CellPathology(); - /// @name Set pathologies - /// @{ - /// @brief Invalid @c CaloCell pointer - /// - /// An invalid @c NULL pointer was found at a given valid index in the @c CaloCellContainer. - /// - /// @param cellhash hash identifier (index in @c CaloCellContainer) for a given @c CaloCell. - /// @param cptr cell pointer (should be @c NULL in this case) - void setInvalidPointer(int cellhash,const CaloCell* cptr); - /// @brief Invalid @c CaloCell hash - /// - /// A cell identifier is found to be out of range. - /// - /// @param cellhash hash identifier (index in @c CaloCellContainer - here invalid!) for a given @c CaloCell. - /// @param cptr cell pointer (should be @c NULL in this case) - void setInvalidHash(int cellhash,const CaloCell* cptr); - /// @brief Invalid sampling identifier for given @c CaloCell - /// - /// The sampling identifier associated with a @c CaloCell is not valid (not in the enumerator list). - /// - /// @param cellhash hash identifier (index in @c CaloCellContainer - here invalid!) for a given @c CaloCell. - /// @param cptr cell pointer (should be @c NULL in this case) - void setInvalidSampling(int cellhash,const CaloCell* cptr); - /// @} - - /// @name Accessors to pathologies stats - /// @{ - const cache_t& invalidPointer() const; ///< @brief Occurances of invalid pointers - const cache_t& invalidHash() const; ///< @brief Occurances of invalid hash identifier - const cache_t& invalidSampling() const; ///< @brief Occurances of invalid sampling identifier - /// @} - - private: - - /// @name Caches - /// @{ - cache_t _invalidPointer; ///< @brief Invalid pointer - cache_t _invalidHash; ///< @brief Invalid hash - cache_t _invalidSampling; ///< @brief Invalid sampling - /// @} - - /// @name Helpers - /// @{ - /// @brief Add a pathology to the cache - /// - /// @param msg message describing pathology - /// @param map cache - void _addMsg(const pathology_t& msg,cache_t& map); - /// @} - }; - - /// @brief Cluster size tag - xAOD::CaloCluster::ClusterSize getClusterSize(const xAOD::CaloTowerContainer& towerCont); - - /// @brief Clean up cell links - remove null pointers - int cleanupCells(CaloClusterCellLink* clk); - - // /// @brief Calculate kinemactics - // bool calculateKine(xAOD::CaloCluster* pClus); - - /// @brief Book keeping - void addWarning(const std::string& msg); - std::map<std::string,unsigned int> m_warning; - void addMessage(const std::string& msg); - std::map<std::string,unsigned int> m_message; - CellPathology m_cellProblems; - void printProblems(const std::map<std::string,int>& map); - - typedef std::vector<CaloProtoCluster*> protocont_t; - - /// @name Helpers - /// @{ - /// @brief Build inclusive tower clusters - /// - /// Fills all cells into proto-clusters. - /// - /// @return @c false in case of problems with data access or inconsistent data structures. - /// - /// @param pCellCont reference to non-modifiable @c CaloCellContainer - /// @param pProtoCont reference to @c CaloProtoCluster container filled on output. - /// - bool buildInclClusters(const CaloCellContainer& pCellCont,protocont_t& pProtoCont); - /// @brief Build exclusive tower clusters + ///@name Tower builders /// - /// Fills cells above energy threshold into proto-clusters. + ///@return @c false in case of problems with data access or inconsistent data structures /// - /// @return @c false in case of problems with data access or inconsistent data structures. + ///@param pCellCont reference to non-modifiable @c CaloCellContainer + ///@param pProtoCont reference to @c CaloProtoCluster container filled on output. + ///@param clusCont reference to non-modifiable @c xAOD::CaloClusterContainer + ///@param protoCont reference to modifiable proto-cluster container /// - /// @param pCellCont reference to non-modifiable @c CaloCellContainer - /// @param pProtoCont reference to @c CaloProtoCluster container filled on output. - bool buildExclClusters(const CaloCellContainer& pCellCont,protocont_t& pProtoCont); - // bool buildFilteredClusters(const CaloCellContainer& pCellCont,protocont_t& pProtoCont); ///< @brief Build tower clusters from topo-cluster cells - /// @brief Add cells to proto-clusters + ///@return + ///@{ + uint_t buildInclTowers(const CaloCellContainer& pCellCont,protocont_t& pProtoCont); ///< Inclusive towers + uint_t buildExclTowers(const CaloCellContainer& pCellCont,protocont_t& pProtoCont); ///< Exclusive towers + uint_t buildEMTopoTowers(const xAOD::CaloClusterContainer& clusCont,protocont_t& protoCont); ///< EM topo-towers + uint_t buildLCWTopoTowers(const xAOD::CaloClusterContainer& clusCont,protocont_t& protoCont); ///< LCW topo-towers + ///@} + /// @brief Adding cells to proto-clusters /// /// @return @c true if cell successfully added to one (or more) proto-clusters /// /// @param cptr pointer ton non-modifiable @c CaloCell object /// @param pProtoCont reference to proto-cluster container - bool addCellToProtoCluster(const CaloCell* cptr,protocont_t& pProtoCont); - /// @} - - /// @brief Cache - CaloCellClusterWeights* m_cellClusterWeights; + /// @param weight additional (global) weight of cell (e.g. for geometrical weight for combined EM-scale signals) + bool addCellToProtoCluster(const CaloCell* cptr,protocont_t& pProtoCont,double weight=1.); + + ///@name Helpers + ///@{ + bool filterProtoCluster(const CaloClusterCellLink& clnk) const; ///< Checks for and removes invalid cell links + bool checkCellIndices(const CaloCellContainer* pCellCont) const; ///< Checks consistency between cell indices and hash identifiers + bool isValidIndex(uint_t idx) const; ///< Checks if argument is a valid index value + uint_t badIndexValue() const; ///< Returns value indicating a bad index + ///@} + + ///@name Excluded samplings + ///@{ + std::vector<CaloSampling::CaloSample> m_excludedSamplings; ///< List of excluded samplings (@c CaloSampling::CaloSample enumerators) + std::vector<std::string> m_excludedSamplingsName; ///< List of excluded samplings (human-readable names) + std::bitset< _CALOTOPOCLUSTERFROMTOWERMAKER_BITSET_SIZE > m_excludedSamplingsPattern; ///< Bit pattern indicates if sampling is excluded + ///@} + + ///@name Monitoring + ///@{ + ///@} }; -inline void CaloTopoClusterFromTowerMaker::CellPathology::_addMsg(const std::string& msg,std::map<std::string,int>& map) -{ if ( map.find(msg) == map.end() ) { map[msg] = 0; } map[msg] += 1; } +inline CaloTopoClusterFromTowerMaker::uint_t CaloTopoClusterFromTowerMaker::badIndexValue() const { return m_errorValueUINT; } +inline bool CaloTopoClusterFromTowerMaker::isValidIndex(uint_t idx) const { return idx != badIndexValue(); } -inline const std::map<std::string,int>& CaloTopoClusterFromTowerMaker::CellPathology::invalidPointer() const -{ return _invalidPointer; } -inline const std::map<std::string,int>& CaloTopoClusterFromTowerMaker::CellPathology::invalidHash() const -{ return _invalidHash; } -inline const std::map<std::string,int>& CaloTopoClusterFromTowerMaker::CellPathology::invalidSampling() const -{ return _invalidSampling; } - -/// @class CaloTopoClusterFromTowerMaker -/// @author Peter Loch <loch@physics.arizona.edu> +///@class CaloTopoClusterFromTowerMaker /// -/// @brief A cluster builder tool forming topo-clusters representing calorimeter tower signals on a regular grid in @f$ (\eta,\phi) @f$ space. +/// @brief A cluster builder tool forming topo-clusters representing calorimeter tower signals on a regular grid in @f$ (\eta,\phi) @f$ space. By default, +/// EM-scale <i>topo-towers</i> are created from cells in topo-clusters. /// -/// This tool provides functionality allowing the creation of topo-cluster collections representing towers. The output data objects are -/// @c xAOD::CaloCluster , collected into @c xAOD::CaloClusterContainer . Several configuration options are supported: +/// This tool fills EM-scale towers and stores them as @c xAOD::CaloCluster. It supports several operational modes, which are +/// controlled by tool properties. It fills a container of type @c xAOD::CaloClusterContainer. The properties controlling its +/// specific behavior are: /// +/// <table width="90%" align="center" style="border-width:0px;"> +/// <tr><td align="center" colspan="4" style="background-color:rgb(245,245,220);color:rgb(165,42,42);"><b>Properties defining tool behavior</b></td></tr> +/// <tr style="color:rgb(131,42,34);"> +/// <td align="left" width="25%">Property name</td> +/// <td align="center" width="25%">Property type</td> +/// <td align="center" width="25%">Default value</td> +/// <td align="left" width="25%">Comment</td> +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>OrderClusterByPt</tt></td> +/// <td align="center" valign="top"><tt>bool</tt></td> +/// <td align="center" valign="top"><tt>false</tt></td> +/// <td align="left" valign="top">if @c true, the @c xAOD::CaloClusterContainer is ordered by @f$ p_{\rm T}^{\rm clus} @f$. See further comments below.</td> +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>PrepareLCW</tt></td> +/// <td align="center" valign="top"><tt>bool</tt></td> +/// <td align="center" valign="top"><tt>false</tt></td> +/// <td align="left" valign="top">if @c true, the tool fills a @c CaloCellClusterWeights object and records it into the event store to be used by @c CaloTopoClusterFromTowerCalibrator</td> +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>UseCellsFromClusters</tt></td> +/// <td align="center" valign="top"><tt>bool</tt></td> +/// <td align="center" valign="top"><tt>true</tt></td> +/// <td align="left" valign="top">if @c true, only cells from topo-clusters are used to fill the towers (<i>topo-towers</i>); else, @a inclusive @a towers are filled with all cells.</td> +/// </tr> +/// <tr><td align="center" colspan="4" style="background-color:rgb(245,245,220);color:rgb(165,42,42);"><b>Properties setting variables for operational modes</b></td></tr> +/// <tr style="color:rgb(131,42,34)"> +/// <td align="left" width="25%">Property name</td> +/// <td align="center" width="25%">Property type</td> +/// <td align="center" width="25%">Default value</td> +/// <td align="left" width="25%">Comment</td> +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>CellEnergyThreshold</tt></td> +/// <td align="center" valign="top"><tt>double</tt></td> +/// <td align="center" valign="top"><tt>m_energyThresholdDef</tt></td> +/// <td align="left" valign="top">cell energy threshold used in exclusive mode only. See further comments below.</td> +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>CellContainerKey</tt></td> +/// <td align="center" valign="top"><tt>SG::ReadHandleKey<CaloCellContainer></tt></td> +/// <td align="center" valign="top"><tt>"AllCalo"</tt></td> +/// <td align="left" valign="top">cell container key is needed to pick up @c CaloCellContainer for all operational modes.</td> +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>ClusterContainerKey</tt></td> +/// <td align="center" valign="top"><tt>SG::ReadHandleKey<xAOD::CaloClusterContainer></tt></td> +/// <td align="center" valign="top"><tt>"CaloTopoCluster"</tt></td> +/// <td align="left" valign="top">cluster container key is needed to pick up @c xAOD::CaloClusterContainer for filtered mode (<tt>UseCellsFromCluster = true</tt>) +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>CellClusterWeightKey</tt></td> +/// <td align="center" valign="top"><tt>SG::WriteHandleKey<CaloCellClusterWeights></tt></td> +/// <td align="center" valign="top"><tt>−N/A−</tt></td> +/// <td align="left" valign="top">key for @c CaloCellClusterWeights object is needed if <tt>PrepareLCW = true</tt>. Default is empty key. +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>BuildCombinedTopoSignal</tt></td> +/// <td align="center" valign="top"><tt>bool</tt></td> +/// <td align="center" valign="top"><tt>false</tt></td> +/// <td align="left" valign="top">turns on combined topo-cluster/topo-tower output, with topo-clusters used within the rapidity range defined by <tt>TopoClusterRange</tt> and topo-towers elsewhere.</td></tr> +/// </tr> +/// <tr> +/// <td align="left" valign="top"><tt>TopoClusterRange</tt></td> +/// <td align="center" valign="top"><tt>double</tt></td> +/// <td align="center" valign="top"><tt>5.</tt></td> +/// <td align="left" valign="top">sets the range @f$ y_{\rm topo-cluster}^{\rm max} @f$ for using topo-clusters when <tt>BuildCombinedTopoSignal = true</tt>; +/// topo-clusters with @f$ \left|y_{\rm topo-cluster}\right| < y_{\rm topo-cluster}^{\rm max} @f$ are used. +/// </tr> +/// </table> +/// +/// The towers can be classified as: /// -# <b>inclusive cell towers</b> -/// All cells are collected into towers, independent of their signal. This is the default behaviour. +/// All cells are collected into inclusive towers, independent of their signal. Requires properties <tt>UseCellsFromClusters = false</tt> and <tt>UseCellEnergyThreshold = false</tt>. Only EM +/// towers are possible, as cells not collected into topo-clustersdo not have a calibration applied. /// -# <b>exclusive cell towers</b> -/// Cells with @f$ E > E_{\rm min} @f$ are collected into towers. This behaviour is turned on by poviding a property @c CellEnergyThreshold setting @f$ E_{\rm min} @f$. +/// Cells with @f$ E > E_{\rm min} @f$ are collected into exclusive towers. This behaviour is turned on by <tt>UseCellsFromClusters = false</tt> and <tt>UseCellEnergyThreshold = true</tt>. A +/// meaningful <tt>CellEnergyThreshold</tt> value needs to be provided in addition. /// -# <b>filtered mode</b> -/// Cells contributing to standard topo-clusters are collected into towers. This behaviour is triggered by providing the @c CaloTopoClusterContainerKey property with a -/// valid key for a topo-cluster collection in the event store. +/// Cells contributing to standard topo-clusters are collected into topo-towers. This behaviour is triggered by <tt>UseCellsFromClusters = true</tt>. Optionally, LCW calibration can be applied +/// to these towers by setting <tt>PrepareLCW = true</tt> and scheduling a @c CaloTopoClusterFromTowerCalibrator tool after the cluster moment calculators. The values of the <tt>UseEnergyThreshold</tt> +/// and <tt>CellEnergyThreshold</tt> properties are ignored in this mode. A valid event store key needs to be provided in the to pick up the topo-cluster container. Note that building EM +/// topo-towers requires topo-clusters on EM scale (no LCW applied) to get the correct geometrical cell weights only. LCW topo-towers require LCW scale topo-clusters to get the correct full geometrical +/// and calibration weights. +/// -# <b>mixed mode</b> +/// Cells contributing to standard topo-clusters are collected into towers if these topo-clusters are outside of a give rapidity range. The rapidity range is defined by the <tt>TopoClusterRange</tt> +/// property. This mode is turned on by setting the property <tt>BuildCombinedTopoSignal = true</tt>. It is turned off by default (<tt>BuildCombinedTopoSignal = false</tt>). +/// EM scale and LCW scale is possible, as in the filtered mode. /// /// Configuration 2 and 3 are exclusive, with 3 overwriting 2. The output topo-clusters represent calorimeter towers on the EM scale. The can be handed to cluster moment /// tools (needs EM scale) and, if desired, to a dedicated cluster calibration tool of type @c xAOD::CaloTowerClusterFromTowerCalibrator . /// -/// To avoid mulitple retrievals of the same weights by searching for cells in (many) topo-clusters, the overall weight of the cell signal is stored in a random access +/// To avoid multiple retrievals of the same weights by searching for cells in (many) topo-clusters, the overall weight of the cell signal is stored in a random access /// look-up table stored in a @c CaloCellClusterWeights object in the detector store. This object is created by this tool, if needed. If the tool property -/// @c CellWeightLookupKey is set, this object will be generated, filled, and recorded. -/// +/// @c CellWeightLookupKey is set, this object will be generated, filled, and recorded. This is essential for calibrated topo-towers! +/// +///@note The @c OrderByPt property, which orders the container by descending transverse momentum, is only useful for EM towers. Applyin LCW may lead to a different +/// order - if a container with LCW towers should be ordered, the corresponding property @c OrderByPt of the @c CaloTopoClusterFromTowerCalibrator tool should +/// be set to @c true. +/// +///@note Many more details on the towers are available on +/// <a href="https://twiki.cern.ch/twiki/bin/view/AtlasSandboxProtected/CaloTowerPerformance" title="https://twiki.cern.ch/twiki/bin/view/AtlasSandboxProtected/CaloTowerPerformance">this page</a>. +/// +/// @author Peter Loch <loch@physics.arizona.edu> #endif diff --git a/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerMonitor.h b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerMonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..52abb14cae72c62adc049bf768c2d524b454455d --- /dev/null +++ b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterFromTowerMonitor.h @@ -0,0 +1,342 @@ +// -*- c++ -*- +#ifndef CALOREC_CALOTOPOCLUSTERFROMTOWERMONITOR_H +#define CALOREC_CALOTOPOCLUSTERFROMTOWERMONITOR_H + +#include "StoreGate/ReadHandleKey.h" + +#include "GaudiKernel/ServiceHandle.h" + +#include "AthenaBaseComps/AthHistogramAlgorithm.h" + +#include "xAODCaloEvent/CaloClusterContainer.h" + +#include "CaloRec/CaloTowerGeometrySvc.h" +#include "CaloRec/CaloTopoClusterFromTowerHelpers.h" + +#include "xAODCaloEvent/CaloCluster.h" +#include "CaloEvent/CaloCell.h" + +#include <vector> +#include <bitset> +#include <map> +#include <cmath> + +#include "TH1D.h" +#include "TH2D.h" + +///@brief Algorithm to monitor kinematics and composition of towers (and clusters) +/// +/// This algorithm fills a few histograms relevant for monitoring tower-related information, As both topo-clusters and towers +/// use the same representation in data, both signal definitions can be monitored - even though most histograms are designed +/// for distributions of tower-specific signal features. +/// +/// The algorithm has several process control properties and configured values: +/// +/// | Property | Default | Controled feature or value +/// :------------------ | :----------: |:------------------------------------------------------------------------------------------- +/// | @c DoGeoAutoBins | @c true | if @c true the binning of @f$ y @f$ and @f$ \phi @f$ is constructed from the tower geometry database; +/// | ^ | ^ | else it is user-defined by the corresponding value property +/// | Hotspot analysis is on if @f$ y_{\rm min}^{\rm hotspot} < y_{\rm max}^{\rm hotspot} @f$ and @f$ \phi_{\rm min}^{\rm hotspot} < \phi_{\rm max}^[\rm hotspot} @f$ (on by defaults) || +/// | @c EtaMinHotspot | 0. | defines lower limit @f$ y_{\rm min}^{\rm hotspot} @f$ of rapidity for the hotspot analysis +/// | @c EtaMaxHotspot | 0.1 | defines upper limit @f$ y_{\rm max}^{\rm hotspot} @f$ of rapidity for the hotspot analysis +/// | @c PhiMinHotspot | 0. | defines lower limit @f$ \phi_{\rm min}^{\rm hotspot} @f$ of azimuth for the hotspot analysis +/// | @c PhiMaxHotspot | 0.1 | defines upper limit @f$ \phi_{\rm max}^{\rm hotspot} @f$ of azimuth for the hotspot analysis +/// | Histogram binning: (pseudo)-rapidity (@f$ y_{\rm min} \geq y_{\rm max} @f$ returns error) || +/// | @c EtaTowersBins | 100 | number of rapidity bins +/// | @c EtaTowersMin | -5. | lower limit of rapidity range @f$ y_{\rm min} @f$ +/// | @c EtaTowersMax | 5. | upper limit of rapidity range @f$ y_{\rm max} @f$ +/// | Histogram binning: azimuth (@f$ \phi_{\rm min \geq \phi_[\rm max} @f$ returns error) || +/// | @c PhiTowersBins | 64 | number of azimuth bins +/// | @c PhiTowersMin | @f$ -\pi @f$ | lower limit of azimuth range @f$ \phi_{\rm min} @f$ +/// | @c PhiTowersMax | @f$ +\pi @f$ | upper limit of azimuth range @f$ \phi_{\rm max} @f$ +/// | Histogram binning: transverse momentum (@f$ p_{\rm T,min} < p_{\rm T,max} @f$ returns error) || +/// | @c PtTowersBins | 220 | number of transverse momentum bins +/// | @c PtTowersMin | -10 GeV | lower limit of transverse momentum range @f$ p_{\rm T,min} @f$ +/// | @c PtTowersMax | 100 GeV | upper limit of transverse momentum range @f$ p_{\rm T,max} @f$ +class CaloTopoClusterFromTowerMonitor : public AthHistogramAlgorithm +{ +public: + + /// Default algorithm constructor + CaloTopoClusterFromTowerMonitor(const std::string& name,ISvcLocator* pSvcLocator); + /// Base-class destructor + virtual ~CaloTopoClusterFromTowerMonitor(); + + ///@brief Initialization + /// + /// This method configures the algorithm, allocates the tower geometry service and books the histograms by + /// invoking the @c book() method. In addition, histograms are filled with geometry information retrieved + /// from the tower geometry service (static information not depending on event variables). + virtual StatusCode initialize(); + ///@brief Execution + /// + /// This method allocates the input data container and fills all histograms. If configured, it also provides + /// + virtual StatusCode execute(); ///< Execution fills histograms. + + +private: + + ///@name Data access properties + ///@{ + SG::ReadHandleKey<xAOD::CaloClusterContainer> m_towerContainerKey; ///< Allocator for input @c xAOD::CaloClusterContainer + ServiceHandle<CaloTowerGeometrySvc> m_towerGeometrySvc; ///< Allocator for tower geometry services + ///@} + + ///@name Histogram binning properties + ///@{ + int m_ncBins; ///< Number of cells in towers - number of bins + double m_ncMin; ///< Number of cells in towers - lower limit of value range + double m_ncMax; ///< Number of cells in towers - upper limit of value range + int m_nBins; ///< Tower multiplicity - number of bins + double m_nMin; ///< Tower multiplicity - lower limit of value range + double m_nMax; ///< Tower multiplicity - upper limit of value range + int m_ptBins; ///< Tower @f$ p_{\rm T} @f$ - number of bins + double m_ptMin; ///< Tower @f$ p_{\rm T} @f$ - lower limit of value range (in GeV) + double m_ptMax; ///< Tower @f$ p_{\rm T} @f$ - upper limit of value range (in GeV) + int m_etaBins; ///< Tower rapidity - number of bins + double m_etaMin; ///< Tower rapidity - lower limit of value range + double m_etaMax; ///< Tower rapidity - upper limit of value range + int m_phiBins; ///< Tower azimuth - number of bins + double m_phiMin; ///< Tower azimuth - lower limit of value range + double m_phiMax; ///< Tower azimuth - upper limit of value range + + double m_hsEtaMin; double m_hsEtaMax; + double m_hsPhiMin; double m_hsPhiMax; + + bool m_doGeoAutoBins; + bool m_doHotspot; + ///@} + + TH1D* h_n; + TH1D* h_pt; + TH1D* h_eta; + TH1D* h_phi; + TH1D* h_nc; + TH1D* h_samp; + + TH2D* d_n_eta_phi; + TH2D* d_nc_eta_phi; + TH2D* d_pt_eta; + TH2D* d_nc_eta; + + TH2D* d_wgt_samp; + TH2D* d_ntt_samp; + TH2D* d_geo_samp; + TH2D* d_maxtowers_samp; + TH2D* d_wgttowers_samp; + + TH2D* d_maxcells_eta; + TH2D* d_allwghts_eta; + + TH2D* d_deta_eta; + TH2D* d_dphi_eta; + TH2D* d_dphi_deta; + + TH2D* d_detac_eta; + TH2D* d_dphic_eta; + TH2D* d_dphic_detac; + + TH2D* d_detac_samp; + TH2D* d_dphic_samp; + + // hot spot + TH1D* h_nc_hs; + TH1D* h_n_hs; + TH1D* h_pt_hs; + TH1D* h_eta_hs; + TH1D* h_phi_hs; + TH1D* h_samp_hs; + + TH2D* d_n_eta_phi_hs; + TH2D* d_nc_eta_phi_hs; + + TH2D* d_deta_eta_hs; + TH2D* d_dphi_eta_hs; + TH2D* d_dphi_deta_hs; + + TH2D* d_detac_eta_hs; + TH2D* d_dphic_eta_hs; + TH2D* d_dphic_detac_hs; + + TH2D* d_detac_samp_hs; + TH2D* d_dphic_samp_hs; + + std::vector<TH2D*> d_maxcells_phi_eta_slice; + std::vector<TH2D*> d_allwghts_phi_eta_slice; + +protected: + + bool isInHotspot(const xAOD::CaloCluster& ptow) const; + bool fillComposition(const xAOD::CaloCluster& ptow,std::vector<double>& deta,std::vector<double>& dphi,std::vector<CaloSampling::CaloSample>& csam) const; + bool setAxisTitle(TH1* h,const std::string& title,const std::string& axis="x"); + + virtual StatusCode book(); + std::bitset<200000> m_cellTags; + + /////////////////////// + // BookAny Templates // + /////////////////////// + + template<class H> + H* bookAny(const std::string& hname,const std::string& htitle,const std::string& xtitle,int nxbins,double xmin,double xmax) { + H* hptr = (H*)bookGetPointer( H(hname.c_str(),htitle.c_str(),nxbins,xmin,xmax) ); + if ( hptr == 0 ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Cannot book distribution \042%s\042 with title \042%s\042",hname.c_str(),htitle.c_str()) ); + } else { + hptr->Sumw2(); + if ( !xtitle.empty() && xtitle != "" ) { hptr->GetXaxis()->SetTitle(xtitle.c_str()); } + } + return hptr; + } + + template<class H> + H* bookAny(const std::string& hname,const std::string& htitle,const std::string& xtitle,int nxbins,double xmin,double xmax,int nybins,double ymin,double ymax) { + H* hptr = (H*)bookGetPointer( H(hname.c_str(),htitle.c_str(),nxbins,xmin,xmax,nybins,ymin,ymax) ); + if ( hptr == 0 ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Cannot book distribution \042%s\042 with title \042%s\042",hname.c_str(),htitle.c_str()) ); + } else { + hptr->Sumw2(); + if ( !xtitle.empty() && xtitle != "" ) { hptr->GetXaxis()->SetTitle(xtitle.c_str()); } + } + return hptr; + } + + template<class H> + H* bookAny(const std::string& hname,const std::string& htitle,const std::string& xtitle, + int nxbins,double xmin,double xmax,int nybins,double ymin,double ymax,int nzbins,double zmin,double zmax) { + H* hptr = (H*)bookGetPointer( H(hname.c_str(),htitle.c_str(),nxbins,xmin,xmax,nybins,ymin,ymax,nzbins,zmin,zmax) ); + if ( hptr == 0 ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Cannot book distribution \042%s\042 with title \042%s\042",hname.c_str(),htitle.c_str()) ); + } else { + hptr->Sumw2(); + if ( !xtitle.empty() && xtitle != "" ) { hptr->GetXaxis()->SetTitle(xtitle.c_str()); } + } + return hptr; + } + + template<class H> + H* bookAny(const std::string& hname,const std::string& htitle,int nxbins,double xmin,double xmax) { + H* hptr = (H*)bookGetPointer( H(hname.c_str(),htitle.c_str(),nxbins,xmin,xmax) ); + if ( hptr == 0 ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Cannot book distribution \042%s\042 with title \042%s\042",hname.c_str(),htitle.c_str()) ); + } else { + hptr->Sumw2(); + hptr->GetXaxis()->SetTitle(hptr->GetTitle()); + } + return hptr; + } + + template<class H> + H* bookAny(const std::string& hname,const std::string& htitle,int nxbins,double xmin,double xmax,int nybins,double ymin,double ymax) { + H* hptr = (H*)bookGetPointer( H(hname.c_str(),htitle.c_str(),nxbins,xmin,xmax,nybins,ymin,ymax) ); + if ( hptr == 0 ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Cannot book distribution \042%s\042 with title \042%s\042",hname.c_str(),htitle.c_str()) ); + } else { + hptr->Sumw2(); + hptr->GetXaxis()->SetTitle(hptr->GetTitle()); + } + return hptr; + } + + template<class H> + H* bookAny(const std::string& hname,const std::string& htitle,int nxbins,double xmin,double xmax,int nybins,double ymin,double ymax,int nzbins,double zmin,double zmax) { + H* hptr = (H*)bookGetPointer( H(hname.c_str(),htitle.c_str(),nxbins,xmin,xmax,nybins,ymin,ymax,nzbins,zmin,zmax) ); + if ( hptr == 0 ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Cannot book distribution \042%s\042 with title \042%s\042",hname.c_str(),htitle.c_str()) ); + } else { + hptr->Sumw2(); + hptr->GetXaxis()->SetTitle(hptr->GetTitle()); + } + return hptr; + } + + //////////////////////// + // Book for Samplings // + //////////////////////// + + template<class H> + H* bookForSamplings(const std::string& hname,const std::string& htitle) { + int nsamp((int)CaloRec::Lookup::getSamplingId("MINIFCAL0")); double xmin(-0.5); double xmax(xmin+1.*(nsamp+1)); + H* hptr = bookAny<H>(hname,htitle,"",nsamp+1,xmin,xmax); + if ( hptr != 0 ) { + for ( int isamp(0); isamp < nsamp; ++isamp ) { + hptr->GetXaxis()->SetBinLabel(isamp+1,CaloRec::Lookup::getSamplingName((CaloSampling::CaloSample)isamp).c_str()); + } + hptr->GetXaxis()->SetBinLabel(hptr->GetNbinsX(),CaloRec::Lookup::getSamplingName(CaloSampling::Unknown).c_str()); + } + return hptr; + } + + template<class H> + H* bookForSamplings(const std::string& hname,const std::string& htitle,int nybins,double ymin,double ymax) { + int nsamp((int)CaloRec::Lookup::getSamplingId("MINIFCAL0")); double xmin(-0.5); double xmax(xmin+1.*(nsamp+1)); + H* hptr = bookAny<H>(hname,htitle,"",nsamp+1,xmin,xmax,nybins,ymin,ymax); + if ( hptr != 0 ) { + for ( int isamp(0); isamp < nsamp; ++isamp ) { + hptr->GetXaxis()->SetBinLabel(isamp+1,CaloRec::Lookup::getSamplingName((CaloSampling::CaloSample)isamp).c_str()); + } + hptr->GetXaxis()->SetBinLabel(hptr->GetNbinsX(),CaloRec::Lookup::getSamplingName(CaloSampling::Unknown).c_str()); + } + return hptr; + } + + /////////////////////// + // Book for Rapidity // + /////////////////////// + + template<class H> + H* bookForEta(const std::string& hname,const std::string& htitle) { return bookAny<H>(hname,htitle,"y_{tower}",m_etaBins,m_etaMin,m_etaMax); } + + template<class H> + H* bookForEta(const std::string& hname,const std::string& htitle,int nybins,double ymin,double ymax) { + return bookAny<H>(hname,htitle,"y_{tower}",m_etaBins,m_etaMin,m_etaMax,nybins,ymin,ymax); + } + + ////////////////////// + // Book for Azimuth // + ////////////////////// + + template<class H> + H* bookForPhi(const std::string& hname,const std::string& htitle) { return bookAny<H>(hname,htitle,"#phi_{tower} [rad]",m_phiBins,m_phiMin,m_phiMax); } + + template<class H> + H* bookForPhi(const std::string& hname,const std::string& htitle,int nybins,double ymin,double ymax) { + return bookAny<H>(hname,htitle,"#phi_{tower} [rad]",m_phiBins,m_phiMin,m_phiMax,nybins,ymin,ymax); + } + + /////////////////// + // Fill Sampling // + /////////////////// + + template<class H> + void fillSampling(H* hptr,CaloSampling::CaloSample csamp) { + int isamp(std::min(static_cast<int>(csamp),static_cast<int>(CaloRec::Lookup::getSamplingId("MINIFCAL0")))); + hptr->Fill(1.*isamp); + } + + template<class H> + void fillSampling(H* hptr,CaloSampling::CaloSample csamp,double yval) { + int isamp(std::min(static_cast<int>(csamp),static_cast<int>(CaloRec::Lookup::getSamplingId("MINIFCAL0")))); + hptr->Fill(1.*isamp,yval); + } + + template<class H> + void fillSampling(H* hptr,CaloSampling::CaloSample csamp,double yval,double zval) { + int isamp(std::min(static_cast<int>(csamp),static_cast<int>(CaloRec::Lookup::getSamplingId("MINIFCAL0")))); + hptr->Fill(1.*isamp,yval,zval); + } +}; // CaloTopoClusterFromTowerMonitor + +inline bool CaloTopoClusterFromTowerMonitor::isInHotspot(const xAOD::CaloCluster& ptow) const +{ return m_doHotspot && ( ptow.eta() >= m_hsEtaMin && ptow.eta() < m_hsEtaMax ) && ( ptow.phi() >= m_hsPhiMin && ptow.phi() < m_hsPhiMax ); } + +inline bool CaloTopoClusterFromTowerMonitor::setAxisTitle(TH1* hptr,const std::string& title,const std::string& axis) { + if ( axis == "x" ) { hptr->GetXaxis()->SetTitle(title.c_str()); return true; } + if ( axis == "y" ) { hptr->GetYaxis()->SetTitle(title.c_str()); return true; } + if ( axis == "z" ) { hptr->GetZaxis()->SetTitle(title.c_str()); return true; } + return false; +} +#endif + + diff --git a/Calorimeter/CaloRec/CaloRec/CaloTopoClusterTowerMerger.h b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterTowerMerger.h new file mode 100644 index 0000000000000000000000000000000000000000..792ae2cf9f7fb14c16004a9d1b33c8f687c24206 --- /dev/null +++ b/Calorimeter/CaloRec/CaloRec/CaloTopoClusterTowerMerger.h @@ -0,0 +1,86 @@ +// -*- c++ -*- + +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + + +#ifndef CALOREC_CALOTOPOCLUSTERTOWERMERGER_H +#define CALOREC_CALOTOPOCLUSTERTOWERMERGER_H + +#include "StoreGate/ReadHandleKey.h" +#include "StoreGate/WriteHandleKey.h" + +#include "AthenaBaseComps/AthAlgorithm.h" + +#include "xAODCaloEvent/CaloCluster.h" +#include "xAODCaloEvent/CaloClusterContainer.h" + +#include <vector> +//#include <tuple> +#include <string> +#include <cmath> + +class CaloTopoClusterTowerMerger : public AthAlgorithm +{ +public: + ///@brief Algorithm constructor + CaloTopoClusterTowerMerger(const std::string& name,ISvcLocator* pSvcLocator); + ///@brief Baseclass destructor + virtual ~CaloTopoClusterTowerMerger(); + + ///@name Algorithm interface + ///@{ + virtual StatusCode initialize(); ///< Initialization sets up read and write handle keys + virtual StatusCode execute(); ///< Execution merges the container contents + ///@} + +private: + + ///@name Internally used types + ///@{ + typedef SG::ReadHandleKey<xAOD::CaloClusterContainer> rhandlekey_t; ///< Input data handle key type + typedef SG::WriteHandleKey<xAOD::CaloClusterContainer> whandlekey_t; ///< Output data handle key type + typedef SG::ReadHandle<xAOD::CaloClusterContainer> rhandle_t; ///< Input data handle type + typedef SG::WriteHandle<xAOD::CaloClusterContainer> whandle_t; ///< Output data handle type + ///@} + + ///@name Algorithm properties + ///@{ + rhandlekey_t m_clusterContainerKey; ///< Input topo-cluster container + rhandlekey_t m_towerContainerKey; ///< Input topo-tower container + whandlekey_t m_topoSignalContainerKey; ///< Output merged (view) container + double m_clusterRange; ///< Rapidity range for topo-clusters + // bool m_copyMoments; ///< Explicitely copy cluster moments + ///@} + + ///@name Helpers + ///@{ + bool makeDeepCopy(const xAOD::CaloCluster& rClus,xAOD::CaloClusterContainer* pClusCont) const; ///< Attaches a deep copy to container, returns @c true if successful. + // bool fillMoments(const xAOD::CaloCluster& rClus); ///< Copies list of filled moments into lookup + bool clusterFilter(const xAOD::CaloCluster& rClus) const; ///< Filter topo-cluster + bool towerFilter(const xAOD::CaloCluster& rTowr) const; ///< Filter topo-tower + StatusCode addContainerWriteHandle(whandle_t& signalHandle); ///< Add a write handle for a container (in CaloClusterStoreHelper from r21.9) + ///@} + + ///@name Moment lookup + ///@{ + // static std::vector<std::tuple<xAOD::CaloCluster::MomentType,std::string> > m_momentMap; ///< Map moment types to human readable names + // static std::vector<xAOD::CaloCluster::MomentType> m_momentList; ///< List of used moments for given tower collection + ///@} +}; + + +inline bool CaloTopoClusterTowerMerger::clusterFilter(const xAOD::CaloCluster& rClus) const { return std::abs(rClus.eta()) <= m_clusterRange; } +inline bool CaloTopoClusterTowerMerger::towerFilter(const xAOD::CaloCluster& /*rTowr*/) const { return true; } + +///@class CaloTopoClusterTowerMerger +/// +/// This algorithm merges objects from two @c xAOD::CaloClusterContainer. In the context of the +/// mixed topo-tower/topo-cluster output, the objects in the topo-cluster container are taken +/// up to a client-defined (symmetric) rapidity range. The rest of the phase space is then filled +/// with the objects from the topo-tower container. It is assumed that the overlap resolution +/// is performed when the topo-tower container is filled. The mixed object container contains deep copies +/// of the objects in the input containers. +/// +#endif diff --git a/Calorimeter/CaloRec/CaloRec/CaloTowerGeometrySvc.h b/Calorimeter/CaloRec/CaloRec/CaloTowerGeometrySvc.h new file mode 100644 index 0000000000000000000000000000000000000000..6d2f445548ea860896ee62dad476ca57bcd72b70 --- /dev/null +++ b/Calorimeter/CaloRec/CaloRec/CaloTowerGeometrySvc.h @@ -0,0 +1,414 @@ +// -*- c++ -*- +#ifndef CALOREC_CALOTOWERGEOMETRYSVC_H +#define CALOREC_CALOTOWERGEOMETRYSVC_H + +/* Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ + +#include "AthenaBaseComps/AthService.h" + +#include "Identifier/IdentifierHash.h" + +#include "CaloGeoHelpers/CaloPhiRange.h" + +#include "CaloDetDescr/CaloDetDescrElement.h" +#include "CaloDetDescr/CaloDetDescrManager.h" + +#include "CaloEvent/CaloCell.h" + +#include <string> +#include <vector> +#include <cmath> +#include <array> +#include <tuple> +#include <fstream> + +///@name Forward declarations +///@{ +///template<class T> class SvcFactory; +///@} + +///@brief Interface accessor for @c CaloTowerGeometrySvc +static const InterfaceID IID_CaloTowerGeometrySvc( "CaloTowerGeometrySvc", 1, 0 ); + +class CaloTowerGeometrySvc : public AthService +{ +protected: + + ///@brief To allow interface queries by the service factory (?) + friend class SvcFactory<CaloTowerGeometrySvc>; + +public: + + ///@name Gaudi interfaces and implementations + ///@{ + static const InterfaceID& interfaceID() { return IID_CaloTowerGeometrySvc; } ///< Interface indentifier needed by Gaudi + virtual StatusCode queryInterface(const InterfaceID& riid, void** ppcInterface); ///< Interface query with fallbacks + ///@} + + ///@{ + typedef std::size_t uint_t; ///< Type for unsigned integer + typedef IdentifierHash::value_type index_t; ///< Type for scalar (pseudorapidity,azimuth) index (is an unsigned int type) + typedef std::tuple<index_t,index_t> towerindex_t; ///< Type for composite (tower) index + typedef std::tuple<index_t,double> element_t; ///< Type storing tower index and geometrical weight + typedef std::vector<element_t> elementvector_t; ///< Type for list of elements holding tower index and list of weights + typedef std::vector<elementvector_t> elementmap_t; ///< Type for lists of lists of elements (lookup table type) + ///@} + + ///@brief Standard constructor + /// + /// Constructs towergrid as defined by properties. + /// + ///@param[in] name name of service (implementation of @c Gaudi::Service ) + ///@param[in] pSvc pointer to service locator (from configuration framework) + CaloTowerGeometrySvc(const std::string& name,ISvcLocator* pSvc); + ///@brief Base class destructor + virtual ~CaloTowerGeometrySvc() { }; + + ///@name Implementation of (Ath)Service interfaces + ///@{ + virtual StatusCode initialize() override; ///< Initialize service + virtual StatusCode finalize() override; ///< Finalize service + // virtual StatusCode queryInterface(const InterfaceID& iid,void** ppvInterface); ///< Need to fix compiler issue (FIXME) + ///@} + + // --- Full documentation of this block after end of class definition! + ///@name Retrieve towers for cells + ///@{ + StatusCode access(const CaloCell* pCell,std::vector<index_t>& towerIdx,std::vector<double>& towerWghts) const; + StatusCode access(IdentifierHash cellHash,std::vector<index_t>& towerIdx,std::vector<double>& towerWghts) const; + elementvector_t getTowers(const CaloCell* pCell) const; + elementvector_t getTowers(IdentifierHash cellHash) const; + ///@} + + ///@name Tower bin descriptors and other size information + ///@{ + uint_t maxCellHash() const; ///< Maximum cell hash value + uint_t totalNumberCells() const; ///< Total number of cells + uint_t etaBins() const; ///< Number of pseudorapidity bins + double etaMin() const; ///< Lower boundary of pseudorapidity range + double etaMax() const; ///< Upper boundary of pseudorapidity range + double etaWidth() const; ///< Width of pseudorapidity bin + uint_t phiBins() const; ///< Number of azimuth bins + double phiMin() const; ///< Lower boundary of azimuth + double phiMax() const; ///< Upper boundary of azimuth + double phiWidth() const; ///< Width of azimuth bin + uint_t towerBins() const; ///< Total number of towers + double towerArea() const; ///< Area of individual tower + ///@} + + ///@name Tower index calculators, translaters, manipulators and converters + ///@{ + index_t etaIndex(const CaloCell* pCell) const; ///< Get tower @f$ \eta @f$ bin index for a calorimeter cell referenced by a pointer + index_t etaIndex(IdentifierHash cellHash) const; ///< Get tower @f$ \eta @f$ bin index for a calorimeter cell referenced by its hash identifier + index_t etaIndex(double eta) const; ///< Get tower @f$ \eta @f$ bin index for a given value of @f$ \eta @f$ + index_t etaIndexFromTowerIndex(index_t towerIdx) const; ///< Get tower @f$ \eta @f$ bin index for a given global tower index + index_t phiIndex(const CaloCell* pCell) const; ///< Get tower @f$ \phi @f$ bin index for a calorimeter cell referenced by a pointer + index_t phiIndex(IdentifierHash cellHash) const; ///< Get tower @f$ \phi @f$ bin index for a calorimeter cell referenced by its hash identifier + index_t phiIndex(double phi) const; ///< Get tower @f$ \phi @f$ bin index for a given value of @f$ \phi @f$ + index_t phiIndexFromTowerIndex(index_t towerIdx) const; ///< Get tower @f$ \phi @f$ bin index for a given global tower index + index_t towerIndex(const CaloCell* pCell) const; ///< Get global tower index for a calorimeter cell referenced by a pointer + index_t towerIndex(IdentifierHash cellHash) const; ///< Get global tower index for a calorimeter cell referenced by its hash identifier + index_t towerIndex(double eta,double phi) const; ///< Get global tower index for a pair of @f$ (\eta,\phi) @f$ values + index_t towerIndex(index_t etaIdx,index_t phiIdx) const; ///< Get global tower index for a pair of @f$ (\eta,\phi) @f$ indices + index_t towerIndex(const element_t& elm) const; ///< Get global tower index from payload data + index_t invalidIndex() const; ///< Returns value of invalid index + bool isInvalidIndex(index_t idx) const; ///< Returns @c true if argument is equal to the value provided by @c invalidIndex() + bool isInvalidIndex(index_t idx,index_t maxIdx) const; ///< Returns @c true if first argument is equal to the value provided by @c invalidIndex() or if first argument is not smaller than second argument + bool isInvalidEtaIndex(index_t idx) const; ///< Returns @c true if argument is not a valid pseudorapidity index + bool isInvalidPhiIndex(index_t idx) const; ///< Returns @c true if argumant is not a valid azimuth index + bool isInvalidTowerIndex(index_t idx) const; ///< Returns @c true if argument is not a valid tower index + ///@} + + ///@name Variable generators using tower indices + ///@{ + double towerEtaLocal(index_t etaIndex) const; ///< Return pseudorapdity from local index (bin center) + double towerPhiLocal(index_t phiIndex) const; ///< Return azimuth from local index (bin center) + double towerEta(index_t towerIndex) const; ///< Return pseudorapidity from global tower index (bin center) + double towerPhi(index_t towerIndex) const; ///< Return azimuth from global tower index (bin center) + double invalidValue() const; ///< Return invalid value + bool isInvalidValue(double val) const; ///< Return @c true if given value is invalid + ///@} + + ///@name Helper functions + ///@{ + double cellWeight(const element_t& elm) const; ///< Retrieve cell signal weight from lookup table entry + double cellWeight(IdentifierHash cellHash,index_t towerIdx) const; ///< Retrieve cell signal weight from cell identifier and tower index + double cellWeight(const CaloCell* pCell, index_t towerIdx) const; ///< Retrieve cell signal weight from pointer to cell object and tower index + ///@} + + ///@name Access to storage + ///@{ + elementmap_t::const_iterator begin() const; ///< Iterator points to first entry in internal look-up table (only @c const access!) + elementmap_t::const_iterator end() const; ///< Iterator marks end of internal look-up table (only @c const access) + size_t size() const; ///< Size of internal look-up table + bool empty() const; ///< Internal look-up table is empty if @c true + ///@} + +private: + + ///@name Helpers + ///@{ + StatusCode f_setupSvc(); ///< Internally used function setting up other services needed by this service + StatusCode f_setupTowerGrid(); ///< Internally used function setting up the lookup store + StatusCode f_setupTowerGridFCal(const CaloDetDescrElement* pCaloDDE,std::ofstream& logger); ///< Internally used function mapping an FCal cell onto the tower grid + StatusCode f_setupTowerGridProj(const CaloDetDescrElement* pCaloDDE,std::ofstream& logger); ///< Internally used function mapping a projective cell onto the tower grid + double f_assign(IdentifierHash cellHash,index_t towerIdx,double wgt); ///< Internally used function assigning tower to cell with update of weight if same tower is already assigned + ///@} + + ///@name Access to detector store and other services and stores + ///@{ + const CaloDetDescrManager* m_caloDDM; ///< Pointer to calorimeter detector description + std::string m_logFileName; ///< Name of log file + ///@} + +protected: + + ///@name Internal stores and derived parameters + ///@{ + elementmap_t m_towerLookup; ///< Cell-to-tower mapping lookup store + double m_towerEtaWidth; ///< Width of tower bin in pseudorapidity + double m_towerPhiWidth; ///< Width of tower bin in azimuth + double m_towerArea; ///< Area of individual tower + uint_t m_towerBins; ///< Maximum number of towers + uint_t m_maxCellHash; ///< Maximum cell hash value + uint_t m_numberOfCells; ///< Total number of cells + ///@} + + ///@name Properties + ///@{ + ///@brief Internally stored tower grid descriptors + uint_t m_towerEtaBins; ///< Number of @f$ \eta @f$ bins + double m_towerEtaMin; ///< Lower boundary @f$ \eta_{\rm min} @f$ + double m_towerEtaMax; ///< Upper boundary @f$ \eta_{\rm max} @f$ + bool m_adjustEta; ///< Adjust FCal cells to eta boundary (default @c true ) + uint_t m_towerPhiBins; ///< Number of @f$ \phi @f$ bins + double m_towerPhiMin; ///< Lower boundary @f$ \phi_{\rm min} @f$ + double m_towerPhiMax; ///< Upper boundary @f$ \phi_{\rm max} @f$ + double m_fcal1Xslice; ///< Number of x slices for cells in FCal1 + double m_fcal1Yslice; ///< Number of y slices for cells in FCal1 + double m_fcal2Xslice; ///< Number of x slices for cells in FCal2 + double m_fcal2Yslice; ///< Number of y slices for cells in FCal2 + double m_fcal3Xslice; ///< Number of x slices for cells in FCal3 + double m_fcal3Yslice; ///< Number of y slices for cells in FCal3 + ///@} + + ///@name Process flags, helpers and numerical constants + ///@{ + static index_t m_invalidIndex; ///< Invalid index indicator + static double m_invalidValue; ///< Return value for out-of-range indices andother invalid conversions to a physical quantity + const CaloDetDescrManager* f_caloDDM() const; ///< Pointer to calorimeter detector description manager + const CaloDetDescrElement* f_caloDDE(const CaloCell* pCell) const; ///< Retrieve calorimeter detector description element for a cell object referenced by a pointer + const CaloDetDescrElement* f_caloDDE(IdentifierHash cellHash) const; ///< Retrieve calorimeter detector description element for a given cell hash identifier + double f_cellEta(const CaloCell* pCell) const; ///< Retrieve calorimeter cell pseudorapidity for a cell object referenced by a pointer + double f_cellEta(IdentifierHash cellHash) const; ///< Retrieve calorimeter cell pseudorapidity for a given cell hash identifier + double f_cellPhi(const CaloCell* pCell) const; ///< Retrieve calorimeter cell azimuth for a cell object referenced by a pointer + double f_cellPhi(IdentifierHash cellHash) const; ///< Retrieve calorimeter cell azimuth for a given cell hash identifier + ///@} + + ///@name Stores + ///@{ + std::array<double,3> m_ndxFCal; ///< Stores number of fragments along x for each FCal module + std::array<double,3> m_ndyFCal; ///< Stores number of fragments along y for each FCal module + std::array<double,3> m_wgtFCal; ///< Stores geometrical weights + ///@} +}; + +//-------------------------------------------------// +// Documentation for grouped methods and functions // +// (removed from before/after method for better // +// formatting by doxygen in html). // +//-------------------------------------------------// + +///@fn StatusCode CaloTowerGeometrySvc::access(const CaloCell* pCell,std::vector<index_t>& towerIdx,std::vector<double>& towerWghts) const +/// +///@brief Retrieve the list of towers associated with a calorimeter cell referenced by a pointer +/// +/// The tower indices and weights are returned in two index-parallel vectors. +/// Previous content of these two vectors is removed if this method finds towers for the cell. +/// +///@return Returns @c StatusCode::SUCCESS if list of towers found, else @s StatusCode::FAILURE. +/// +///@param[in] pCell pointer to non-modifiable @c CaloCell object. +///@param[in] towerIdx reference to modifiable vector of indices (payload type @c index_t ); vector is filled if cell is successfully mapped. +///@param[in] towerWghts reference to modifiable vector of weights (payload type @c double ); vector is filled if cell is successfully mapped. + +///@fn StatusCode CaloTowerGeometrySvc::access(IdentifierHash cellHash,std::vector<index_t>& towerIdx,std::vector<double>& towerWghts) const; +/// +///@brief Retrieve the list of towers associated with a calorimeter cell referenced its hash identifier +/// +/// The tower indices and weights are returned in two index-parallel vectors. +/// Previous content of these two vectors is removed if this method finds towers for the cell. +/// +///@return Returns @c StatusCode::SUCCESS if list of towers found, else @s StatusCode::FAILURE. +/// +///@param[in] cellHash hash identifier referencing a calorimeter cell. +///@param[in] towerIdx reference to modifiable vector of indices (payload type @c index_t ); vector is filled if cell is successfully mapped. +///@param[in] towerWghts reference to modifiable vector of weights (payload type @c double ); vector is filled if cell is successfully mapped. + +///@fn CaloTowerGeometrySvc::elementvector_t CaloTowerGeometrySvc::getTowers(const CaloCell* pCell) const; +/// +///@brief Retrieve the list of towers associated with a calorimeter cell referenced by a pointer +/// +///@return Returns a vector of (index,weight) pairs as a @c elementvector_t container. The container is empty +/// if the cell does not have any overlap with a tower. +/// +///@param[in] pCell pointer to non-modifiable @c CaloCell object. + +///@fn CaloTowerGeometrySvc::elementvector_t CaloTowerGeometrySvc::getTowers(IdentifierHash cellHash) const; +/// +///@brief Retrieve the list of towers associated with a calorimeter cell referenced by its hash identifier +/// +///@return Returns a vector of (index,weight) pairs as a @c elementvector_t container. The container is empty +/// if the cell does not have any overlap with a tower. +/// +///@param[in] cellHash hash identifier referencing a calorimeter cell. + +//---------------------// +// Class documentation // +//---------------------// + +/// @class CaloTowerGeometrySvc +/// +/// @brief Tower geometry store and description provider +/// +/// This service sets up a lookup table storing the geometrical area overlap fraction of a calorimeter cell +/// with towers in a given grid. This lookup table is set up at instantiation of the service. It can only be +/// defined at that time. The default setup is a @f$ \Delta\eta\times\Delta\phi = 0.1 \times \pi/32 @f$ grid. +/// Any regular grid can be constructed. The grid definition can be provided as property. +/// +/// The cell-to-tower information is stored internally as a (random access) lookup table. For a given cell, +/// the hash index is used to retrieve a list of towers this cell overlaps with, and the overlap paramater +/// (area fraction used as a geometrical weight). This indices and geometrical weights are represented by +/// a list of pairs of @c int and @c double numbers. Each cell can potential overlap with more than one +/// tower. A more detailed description of towers and the geometrical overlap is available on the +/// <a href="https://twiki.cern.ch/twiki/bin/view/AtlasSandboxProtected/CaloTowerPerformance">calorimeter tower project page</a>. +/// +/// The lookup table is implemented for random access and using the cell hash identifier to retrieve the +/// requested list of twoer indices and weights. Several retrieval mechanisms are supported (see documentation +/// of the corresponding methods). +/// +/// To map the azimuth of a cell to a tower, @f$ -\pi < \phi < \pi @f$ is used (ATLAS standard). For +/// consistency, all @f$ \phi @f$ values are mapped into this range. +/// +/// The service inherits from @c AthService and thus from the @c Service base class in Gaudi. The managed tower grid +/// is defined by service properties, with the following naming convention: +/// - pseudorapidity range +/// - number of bins <tt>TowerEtaBins</tt> (default 100) +/// - lower boundary of pseudorapidity range <tt>TowerEtaMin</tt> (default -5.0) +/// - upper boundary of pseudorapidity range <tt>TowerEtaMax</tt> (default 5.0) +/// - azimuth range +/// - number of bins <tt>TowerPhiBins</tt> (default 64) +/// - lower boundary of azimuthal range <tt>TowerPhiMin</tt> (default -π) +/// - upper boundary of azimuthal range <tt>TowerPhiMax</tt> (default π) +/// +/// Addtional properties of this service define the granularity of the cell splitting in the ATLAS FCal. This +/// is used to map the FCal readout cells (rectangular slabs) onto the tower grid and calculate the geometrical +/// (area) overlap fraction, which is used to distribute the cell energy to the towers. +/// - horizontal FCal cell splitting (along @a x axis) +/// - number of @a x slices in FCal1 <tt>FCal1NSlicesX</tt> (default 4) +/// - number of @a x slices in FCal2 <tt>FCal2NSlicesX</tt> (default 4) +/// - number of @a x slices in FCal3 <tt>FCal3NSlicesX</tt> (default 6) +/// - vertical FCal cell splitting (along @a y axis) +/// - number of @a y slices in FCal1 <tt>FCal1NSlicesY</tt> (default 4) +/// - number of @a y slices in FCal2 <tt>FCal2NSlicesY</tt> (default 6) +/// - number of @a y slices in FCal3 <tt>FCal3NSlicesY</tt> (default 6) +/// +/// @warning It is recommended to @b not change the parameters for the FCal cell slicing. This configuration option is provided for expert use for R & D purposes only. +/// +/// @todo Allow regional grids (varying segmentation as function of @f$ \eta @f$ . This requires additional interfaces (or interface changes) and +/// and modifications of the index construction. +/// +/// @author Peter Loch <loch@physics.arizona.edu> +/// + +//------------------// +// Inline Functions // +//------------------// + +//---------------------------// +// Control and configuration // +//---------------------------// +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::invalidIndex() const { return m_invalidIndex; } +inline StatusCode CaloTowerGeometrySvc::f_setupSvc() { + m_caloDDM = CaloDetDescrManager::instance(); + return f_caloDDM() != 0 ? StatusCode::SUCCESS : StatusCode::FAILURE; +} + +//------------------------------------// +// Public access to tower descriptors // +//------------------------------------// +inline CaloTowerGeometrySvc::uint_t CaloTowerGeometrySvc::maxCellHash() const { return m_maxCellHash; } +inline CaloTowerGeometrySvc::uint_t CaloTowerGeometrySvc::totalNumberCells() const { return m_numberOfCells; } + +inline CaloTowerGeometrySvc::uint_t CaloTowerGeometrySvc::etaBins() const { return m_towerEtaBins; } +inline double CaloTowerGeometrySvc::etaMin() const { return m_towerEtaMin; } +inline double CaloTowerGeometrySvc::etaMax() const { return m_towerEtaMax; } +inline double CaloTowerGeometrySvc::etaWidth() const { return m_towerEtaWidth; } + +inline CaloTowerGeometrySvc::uint_t CaloTowerGeometrySvc::phiBins() const { return m_towerPhiBins; } +inline double CaloTowerGeometrySvc::phiMin() const { return m_towerPhiMin; } +inline double CaloTowerGeometrySvc::phiMax() const { return m_towerPhiMax; } +inline double CaloTowerGeometrySvc::phiWidth() const { return m_towerPhiWidth; } + +inline CaloTowerGeometrySvc::uint_t CaloTowerGeometrySvc::towerBins() const { return m_towerBins; } +inline double CaloTowerGeometrySvc::towerArea() const { return m_towerArea; } + +//----------------// +// Index checking // +//----------------// +inline bool CaloTowerGeometrySvc::isInvalidIndex(index_t idx) const { return idx == invalidIndex(); } +inline bool CaloTowerGeometrySvc::isInvalidIndex(index_t idx,index_t maxIdx) const { return idx == invalidIndex() || idx >= maxIdx; } +inline bool CaloTowerGeometrySvc::isInvalidEtaIndex(index_t idx) const { return isInvalidIndex(idx,m_towerEtaBins); } +inline bool CaloTowerGeometrySvc::isInvalidPhiIndex(index_t idx) const { return isInvalidIndex(idx,m_towerPhiBins); } +inline bool CaloTowerGeometrySvc::isInvalidTowerIndex(index_t idx) const { return isInvalidIndex(idx,m_towerBins); } + +//------------------------------// +// Index retrieval/construction // +//------------------------------// +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::etaIndex(const CaloCell* pCell) const { return etaIndex(pCell->eta()); } +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::phiIndex(const CaloCell* pCell) const { return phiIndex(pCell->phi()); } + +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::towerIndex(IdentifierHash cellHash) const { return towerIndex(etaIndex(cellHash),phiIndex(cellHash)); } +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::towerIndex(double eta,double phi) const { return towerIndex(etaIndex(eta),phiIndex(phi)); } +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::towerIndex(index_t etaIdx,index_t phiIdx) const { return !isInvalidEtaIndex(etaIdx) && !isInvalidPhiIndex(phiIdx) ? phiIdx+etaIdx*m_towerPhiBins : invalidIndex(); } +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::towerIndex(const CaloCell* pCell) const { return towerIndex(pCell->eta(),pCell->phi()); } +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::towerIndex(const element_t& elm) const { return std::get<0>(elm); } + +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::etaIndexFromTowerIndex(index_t towerIdx) const { return (index_t)(towerIdx/phiBins()); } +inline CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::phiIndexFromTowerIndex(index_t towerIdx) const { return (index_t)(towerIdx%phiBins()); } + +//-----------------------------// +// Access to tower description // +//-----------------------------// + +inline double CaloTowerGeometrySvc::invalidValue() const { return m_invalidValue; } +inline bool CaloTowerGeometrySvc::isInvalidValue(double val) const { return val == invalidValue(); } +inline double CaloTowerGeometrySvc::towerEtaLocal(index_t etaIdx) const { return !isInvalidEtaIndex(etaIdx) ? etaMin()+(static_cast<double>(etaIdx)+0.5)*etaWidth() : invalidValue(); } +inline double CaloTowerGeometrySvc::towerPhiLocal(index_t phiIdx) const { return !isInvalidPhiIndex(phiIdx) ? phiMin()+(static_cast<double>(phiIdx)+0.5)*phiWidth() : invalidValue(); } +inline double CaloTowerGeometrySvc::towerEta(index_t towerIdx) const { return towerEtaLocal(etaIndexFromTowerIndex(towerIdx)); } +inline double CaloTowerGeometrySvc::towerPhi(index_t towerIdx) const { return towerPhiLocal(phiIndexFromTowerIndex(towerIdx)); } + +inline CaloTowerGeometrySvc::elementmap_t::const_iterator CaloTowerGeometrySvc::begin() const { return m_towerLookup.begin(); } +inline CaloTowerGeometrySvc::elementmap_t::const_iterator CaloTowerGeometrySvc::end() const { return m_towerLookup.end(); } +inline size_t CaloTowerGeometrySvc::size() const { return m_towerLookup.size(); } +inline bool CaloTowerGeometrySvc::empty() const { return m_towerLookup.empty(); } + +//-------------------// +// Other data access // +//-------------------// +inline double CaloTowerGeometrySvc::cellWeight(const CaloCell* pCell,index_t towerIdx) const { return cellWeight(pCell->caloDDE()->calo_hash(),towerIdx); } +inline double CaloTowerGeometrySvc::cellWeight(const element_t& elm) const { return std::get<1>(elm); } + + +//----------------------------------// +// Internal functions and accessors // +//----------------------------------// +inline const CaloDetDescrManager* CaloTowerGeometrySvc::f_caloDDM() const { return m_caloDDM; } +inline const CaloDetDescrElement* CaloTowerGeometrySvc::f_caloDDE(const CaloCell* pCell) const { return pCell->caloDDE(); } +inline const CaloDetDescrElement* CaloTowerGeometrySvc::f_caloDDE(IdentifierHash cellHash) const { return f_caloDDM()->get_element(cellHash); } + +inline double CaloTowerGeometrySvc::f_cellEta(IdentifierHash cellHash) const { return f_caloDDE(cellHash)->eta(); } +inline double CaloTowerGeometrySvc::f_cellEta(const CaloCell* pCell) const { return pCell->eta(); } +inline double CaloTowerGeometrySvc::f_cellPhi(IdentifierHash cellHash) const { return CaloPhiRange::fix(f_caloDDE(cellHash)->phi()); } +inline double CaloTowerGeometrySvc::f_cellPhi(const CaloCell* pCell) const { return pCell->phi(); } +#endif diff --git a/Calorimeter/CaloRec/python/CaloRecFlags.py b/Calorimeter/CaloRec/python/CaloRecFlags.py index bb6f10ecd1022ec247009a4d03861282596929ee..5f94d15e10d139c3611e4e85cd4d0becd458ec86 100644 --- a/Calorimeter/CaloRec/python/CaloRecFlags.py +++ b/Calorimeter/CaloRec/python/CaloRecFlags.py @@ -87,7 +87,6 @@ class doCaloTowerFromCluster(CaloRecFlagsJobProperty): allowedTypes=['bool'] StoredValue=False - class doCaloTopoTower(CaloRecFlagsJobProperty): """ switch noise suppressed towers based on standard tower + topo clusters """ @@ -95,6 +94,20 @@ class doCaloTopoTower(CaloRecFlagsJobProperty): allowedTypes=['bool'] StoredValue=False +class doCaloTopoSignal(CaloRecFlagsJobProperty): + """ produce mixed topo-cluster and topo-tower container + """ + statusOn=True + allowedTypes=['bool'] + storedValue=False + +class doExtendedClusterMoments(CaloRecFlagsJobProperty): + """ add more cluster moments for R&D + """ + statusOn=True + allowedTypes=['bool'] + storedValue=False + class doTileMuId(CaloRecFlagsJobProperty): """ switch for TileMuId - muon finding algorighm """ @@ -170,7 +183,7 @@ jobproperties.add_Container(CaloRecFlags) # I want always the following flags in the Rec container -_list_Calo=[Enabled,doCaloTopoCluster,doEmCluster,doCaloEMTopoCluster,emTopoClusterThreshold,doCaloCluster,doCaloTopoTower,doTileMuId,doTileCellCorrection,doLArAffectedRegion,doLArAutoConfiguration,doLArNoisyRO,doEMDigits,doFillMBTSBackgroundBit,doLArNoiseBurstVeto,clusterCellGetterName,doCaloTowerFromCells,doCaloTowerFromCluster] +_list_Calo=[Enabled,doCaloTopoCluster,doEmCluster,doCaloEMTopoCluster,emTopoClusterThreshold,doCaloCluster,doCaloTopoTower,doCaloTopoSignal,doExtendedClusterMoments,doTileMuId,doTileCellCorrection,doLArAffectedRegion,doLArAutoConfiguration,doLArNoisyRO,doEMDigits,doFillMBTSBackgroundBit,doLArNoiseBurstVeto,clusterCellGetterName,doCaloTowerFromCells,doCaloTowerFromCluster] for j in _list_Calo: jobproperties.CaloRecFlags.add_JobProperty(j) del _list_Calo diff --git a/Calorimeter/CaloRec/python/MakeClustersFromTowers.py b/Calorimeter/CaloRec/python/MakeClustersFromTowers.py index 6bc75b051bf3c1f72f4a94ab13a76ad389879347..afa1f7e3cc89f884175c9d573e5b8d8c840c280b 100644 --- a/Calorimeter/CaloRec/python/MakeClustersFromTowers.py +++ b/Calorimeter/CaloRec/python/MakeClustersFromTowers.py @@ -1,164 +1,261 @@ # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -from CaloRec.CaloRecConf import CaloTowerxAODFromCells -from CaloRec.CaloRecConf import CaloTopoClusterFromTowerMaker +from AthenaCommon.AppMgr import ServiceMgr as svcMgr -from AthenaCommon.Logging import logging +from CaloRec.CaloRecConf import CaloTopoClusterFromTowerMaker +from CaloRec.CaloRecConf import CaloTowerGeometrySvc +from AthenaCommon.Logging import logging import AthenaCommon.Constants as Lvl -def ClustersFromTowersDict(clusterBuilderName='TowerFromClusterMaker', - towerBuilderAlgo=CaloTowerxAODFromCells('CmbTowerAlgo'), - orderedClusterByPt=False, - doLCW=False, #### don't apply LCW by default - caloTopoClusterKey='NONE', #### all cells is default - caloCellClusterWeightKey='NONE'): #### no cell weight data object needed +#################################### +## Tower configuration dictionary ## +#################################### + +def ClustersFromTowersDict(clusterBuilderName = 'TowerFromClusterTool', + towerGeometrySvc = CaloTowerGeometrySvc('CaloTowerGeometrySvc'), + cellContainerKey = 'AllCalo', + buildTopoTowers = True, + topoClusterContainerKey = 'CaloTopoCluster', + cellClusterWeightKey = 'CaloCellClusterWeightKey', + orderClusterByPt = False, + applyCellEnergyThreshold = False, + doCellIndexCheck = False, + cellEnergyThreshold = 0., + applyLCW = False, + buildCombinedSignal = False, + clusterRange = 5.): ''' Configuration dictionary for tower-to-cluster converter ''' - configDict = { 'ClusterBuilderName' : clusterBuilderName, - 'CaloTowerBuilder' : towerBuilderAlgo, - 'OrderClusterByPt' : orderedClusterByPt, - 'CaloTopoClusterContainerKey' : caloTopoClusterKey, - 'CellClusterWeightKey' : caloCellClusterWeightKey, - 'ApplyLCW' : doLCW + configDict = { 'ClusterBuilderName' : clusterBuilderName, ### name of the tower builder tool + 'CaloTowerGeometrySvc' : towerGeometrySvc, ### tower geometry provider + 'CaloCellContainerKey' : cellContainerKey, ### (input) cell container key + 'CaloTopoClusterContainerKey' : topoClusterContainerKey, ### (input) topo-cluster container key + 'CellClusterWeightKey' : cellClusterWeightKey, ### (output) cell weights in topo-clusters + 'BuildTopoTowers' : buildTopoTowers, ### (control) form topo-towers + 'OrderClusterByPt' : orderClusterByPt, ### (control) order final clusters by Pt + 'ApplyCellEnergyThreshold' : applyCellEnergyThreshold, ### (control) apply energy thresholds to cells + 'CellEnergyThreshold' : cellEnergyThreshold, ### (control) value of energy threshold + '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 } return configDict -def MakeClustersFromTowers(clusterMakerName='CaloClusterMaker',clusterContainerKey='TowerTopoCluster',configDict=ClustersFromTowersDict(),applyEnergyThreshold=False,debugOn=False): - ''' This function generates an instance of a cluster algorithm producting clusters trom towers with or without moments +################################### +## Tower algorithm configuration ## +################################### + +def MakeClustersFromTowers(towerMakerName = 'CaloTowerBuilderAlg', ### name of tower builder algorithm + towerContainerKey = 'CaloTowerTopoCluster', ### output container key + configDict = ClustersFromTowersDict(), ### tower builder tool configuration + debugOn = False): + ''' This function generates an instance of a cluster algorithm configuration producting clusters trom towers with or without moments. ''' - # collect inputs mlog = logging.getLogger('MakeClustersFromTowers.py:: ') - mlog.info('ClusterMakerName = "'+clusterMakerName+'"') - mlog.info('ClusterContainerKey = <'+clusterContainerKey+'>') - mlog.info('Converter parameters: ',configDict) - - # configure cluster builder - cnvname = configDict['ClusterBuilderName'] - twralgo = configDict['CaloTowerBuilder'] - towerkey = twralgo.CaloTowerContainer - mlog.info('(input) CaloTowerContainer <'+towerkey+'>') - cellkey = 'AllCalo' ### twralgo.InputCellContainer --> this does not work, why? - mlog.info('(input) CaloCellContainer <'+cellkey+'>') - ptorder = configDict['OrderClusterByPt'] - tcluskey = configDict['CaloTopoClusterContainerKey'] - tcwgtkey = configDict['CellClusterWeightKey'] - #### buildtt = ( tcluskey != 'NONE' and tcwgtkey != 'NONE' ) - buildtt = configDict['ApplyLCW'] - ''' Configuration module for the tower converter + mlog.info('TowerMakerName = "'+towerMakerName+'"') + mlog.info('TowerContainerKey = <'+towerContainerKey+'>') + + ######################################## + ## Configuring the tower builder tool ## + ######################################## + + ''' collect properties from dictionary and set correct dependencies + ''' + mlog.info('Converter properties: ',configDict) + excludedKeys = [ 'ClusterBuilderName' ] + if configDict['PrepareLCW']: + towerBuilder = CaloTopoClusterFromTowerMaker(configDict['ClusterBuilderName'],OrderClusterByPt=False) ### order by pt after LCW calibration! + excludedKeys += [ 'OrderClusterByPt' ] + else: + towerBuilder = CaloTopoClusterFromTowerMaker(configDict['ClusterBuilderName']) + + ''' Copy properties from dictionary ''' - towerConverter = CaloTopoClusterFromTowerMaker(cnvname,CaloTowerContainerKey=towerkey,CaloCellContainerKey=cellkey,OrderClusterByPt=ptorder) - ''' Refinement of converter configuration + for key,value in configDict.items(): + if key not in excludedKeys: + setattr(towerBuilder,key,value) + + ''' Check basic consistency of configuration + ''' + mlog.info('Consistency check') + if towerBuilder.PrepareLCW and not towerBuilder.BuildTopoTowers: + raise RuntimeError('{0}[inconsistent configuration] applying LCW requires to build topo-towers'.format(towerBuilder.name())) + if towerBuilder.BuildCombinedTopoSignal and not towerBuilder.BuildTopoTowers: + raise RuntimeError('{0}[inconsistent configuration] building combined topo-cluster/topo-tower signals requires to build topo-towers'.format(towerBuilder.name())) + if towerBuilder.ApplyCellEnergyThreshold and towerBuilder.BuildTopoTowers: + raise RuntimeError('{0}[inconsistent configuration] applying cell energy thresholds for topo-towres not yet implemented'.format(towerBuilder.name())) + + ''' Tower converter configuration summary + ''' + if towerBuilder.BuildTopoTowers: + if towerBuilder.PrepareLCW: + ''' LCW topo-towers + ''' + mlog.info('################################################') + mlog.info('## Produce LCW calibrated topo-tower clusters ##') + mlog.info('################################################') + mlog.info('CaloTopoClusterContainerKey .. {0}'.format(towerBuilder.CaloTopoClusterContainerKey)) + mlog.info('CellClusterWeightKey ......... {0}'.format(towerBuilder.CellClusterWeightKey)) + else: + ''' EM topo-towers + ''' + mlog.info('###############################################') + mlog.info('## Produce EM calibrated topo-tower clusters ##') + mlog.info('###############################################') + mlog.info('CaloTopoClusterContainerKey .. {0}'.format(towerBuilder.CaloTopoClusterContainerKey)) + + if towerBuilder.BuildCombinedTopoSignal: + mlog.info(' ') + mlog.info('Combined topo-cluster/topo-towermode with y_max = {0}'.format(towerBuilder.TopoClusterRange)) + else: + ''' EM towers + ''' + mlog.info('########################################') + mlog.info('## Produce EM standard tower clusters ##') + mlog.info('########################################') + + ''' Set debug flag (not a property in the dictionary) ''' - mlog.info(' ') - if buildtt: - mlog.info('################################################') - mlog.info('## Produce LCW calibrated topo-tower clusters ##') - mlog.info('################################################') - mlog.info('CaloTopoClusterContainerKey .. {0}'.format(tcluskey)) - mlog.info('CellClusterWeightKey ......... {0}'.format(tcwgtkey)) - towerConverter.CaloTopoClusterContainerKey = tcluskey - towerConverter.CellClusterWeightKey = tcwgtkey - towerConverter.ApplyLCW = True - else: - mlog.info('####################################################') - mlog.info('## Produce EM calibrated inclusive tower clusters ##') - mlog.info('####################################################') - mlog.info(' ') - if applyEnergyThreshold: - towerConverter.CellEnergyThreshold = twralgo.CellEnergyThreshold if debugOn: - towerConverter.OutputLevel = Lvl.DEBUG - # setting up the moments: external tools + towerBuilder.OutputLevel = Lvl.DEBUG + + towerCoreName = towerMakerName + if towerCoreName.find('Builder') > 0: + (towerCoreName.replace('Builder',' ')).rstrip(' ') + elif towerCoreName.find('Maker') > 0: + (towerCoreName.replace('Maker',' ')).rstrip(' ') + + ############################ + ## Setting up the moments ## + ############################ + + ''' External tools for moment calculation + ''' from CaloTools.CaloNoiseToolDefault import CaloNoiseToolDefault - caloNoiseTool = CaloNoiseToolDefault() from AthenaCommon.AppMgr import ToolSvc - ToolSvc += caloNoiseTool + caloNoiseTool = CaloNoiseToolDefault() + ToolSvc += caloNoiseTool - # moment maker + ''' Cluster moment maker (all general moments) + ''' from CaloRec.CaloTopoClusterFlags import jobproperties - from AthenaCommon.SystemOfUnits import deg, GeV, MeV - from CaloRec.CaloRecConf import CaloClusterMomentsMaker - clusterMoments = CaloClusterMomentsMaker (clusterMakerName+'MomentMaker') - clusterMoments.MaxAxisAngle = 20*deg - clusterMoments.CaloNoiseTool = caloNoiseTool - clusterMoments.UsePileUpNoise = True + from AthenaCommon.SystemOfUnits import deg, GeV, MeV + from CaloRec.CaloRecConf import CaloClusterMomentsMaker + clusterMoments = CaloClusterMomentsMaker (towerMakerName+'MomentMaker') + clusterMoments.MaxAxisAngle = 20*deg + clusterMoments.CaloNoiseTool = caloNoiseTool + clusterMoments.UsePileUpNoise = True clusterMoments.TwoGaussianNoise = jobproperties.CaloTopoClusterFlags.doTwoGaussianNoise() clusterMoments.MinBadLArQuality = 4000 - clusterMoments.MomentsNames = ["FIRST_PHI" - ,"FIRST_ETA" - ,"SECOND_R" - ,"SECOND_LAMBDA" - ,"DELTA_PHI" - ,"DELTA_THETA" - ,"DELTA_ALPHA" - ,"CENTER_X" - ,"CENTER_Y" - ,"CENTER_Z" - ,"CENTER_MAG" - ,"CENTER_LAMBDA" - ,"LATERAL" - ,"LONGITUDINAL" - ,"FIRST_ENG_DENS" - ,"ENG_FRAC_EM" - ,"ENG_FRAC_MAX" - ,"ENG_FRAC_CORE" - ,"SECOND_ENG_DENS" - ,"ISOLATION" - ,"ENG_BAD_CELLS" - ,"N_BAD_CELLS" - ,"N_BAD_CELLS_CORR" - ,"BAD_CELLS_CORR_E" - ,"BADLARQ_FRAC" - ,"ENG_POS" - ,"SIGNIFICANCE" - ,"CELL_SIGNIFICANCE" - ,"CELL_SIG_SAMPLING" - ,"AVG_LAR_Q" - ,"AVG_TILE_Q" - ,"PTD" - ,"MASS" - ] - - # only add HV related moments if it is offline. + clusterMoments.MomentsNames = [ + "FIRST_PHI" + ,"FIRST_ETA" + ,"SECOND_R" + ,"SECOND_LAMBDA" + ,"DELTA_PHI" + ,"DELTA_THETA" + ,"DELTA_ALPHA" + ,"CENTER_X" + ,"CENTER_Y" + ,"CENTER_Z" + ,"CENTER_MAG" + ,"CENTER_LAMBDA" + ,"LATERAL" + ,"LONGITUDINAL" + ,"FIRST_ENG_DENS" + ,"ENG_FRAC_EM" + ,"ENG_FRAC_MAX" + ,"ENG_FRAC_CORE" + ,"SECOND_ENG_DENS" + ,"ISOLATION" + ,"ENG_BAD_CELLS" + ,"N_BAD_CELLS" + ,"N_BAD_CELLS_CORR" + ,"BAD_CELLS_CORR_E" + ,"BADLARQ_FRAC" + ,"ENG_POS" + ,"SIGNIFICANCE" + ,"CELL_SIGNIFICANCE" + ,"CELL_SIG_SAMPLING" + ,"AVG_LAR_Q" + ,"AVG_TILE_Q" + ,"PTD" + ,"MASS" + ] + + ''' HV related moments for offline data + ''' from IOVDbSvc.CondDB import conddb if not conddb.isOnline: from LArRecUtils.LArHVScaleRetrieverDefault import LArHVScaleRetrieverDefault - clusterMoments.LArHVScaleRetriever=LArHVScaleRetrieverDefault() - clusterMoments.MomentsNames += ["ENG_BAD_HV_CELLS" - ,"N_BAD_HV_CELLS" - ] + clusterMoments.LArHVScaleRetriever = LArHVScaleRetrieverDefault() + clusterMoments.MomentsNames += ["ENG_BAD_HV_CELLS","N_BAD_HV_CELLS"] - # cluster maker + ############################################################### + ## Set up the tower builder algorithm - as a cluster builder ## + ############################################################### + + ''' Basic algorithm properties + ''' from CaloRec.CaloRecConf import CaloClusterMaker - clusterMaker = CaloClusterMaker(clusterMakerName) - clusterMaker.ClustersOutputName = clusterContainerKey - clusterMaker.ClusterMakerTools = [ towerConverter ] - mlog.info('instantiated CaloClusterMaker "{0}"'.format(clusterMaker.name())) + towerMaker = CaloClusterMaker(towerMakerName) + towerMaker.ClustersOutputName = towerContainerKey + towerMaker.ClusterMakerTools = [ towerBuilder ] + towerMaker += towerBuilder + mlog.info('instantiated CaloClusterMaker "{0}" configuration'.format(towerMaker.name())) - # bad cell corrections -## from CaloClusterCorrection.CaloClusterBadChannelListCorr import CaloClusterBadChannelListCorr -## badChannelCorr = CaloClusterBadChannelListCorr() + ''' Set up bad cell corrections + ''' + from CaloClusterCorrection.CaloClusterBadChannelListCorr import CaloClusterBadChannelListCorr + badChannelCorr = CaloClusterBadChannelListCorr() - # Correction tools -## clusterMaker.ClusterCorrectionTools += [ badChannelCorr ] - clusterMaker.ClusterCorrectionTools += [ clusterMoments ] + ''' Register correction and moment tools + ''' + towerMaker.ClusterCorrectionTools += [ badChannelCorr ] + towerMaker.ClusterCorrectionTools += [ clusterMoments ] + towerMaker += clusterMoments - # configuring the algorithm - clusterMaker += towerConverter -## clusterMaker += badChannelCorr - clusterMaker += clusterMoments + #################################### + ## Configure LCW calibration tool ## + #################################### - if buildtt: + if towerBuilder.PrepareLCW: from CaloRec.CaloRecConf import CaloTopoClusterFromTowerCalibrator - calgname = clusterMakerName+'Calibrator' - mlog.info('TopoTowers: add LCW calibration tool <'+calgname+'>') - clusterCalibrator = CaloTopoClusterFromTowerCalibrator(calgname) - mlog.info('TopoTowers: '+calgname+'.CellClusterWeightKey = "'+tcwgtkey+'"') - clusterCalibrator.CellClusterWeightKey = tcwgtkey - clusterCalibrator.OrderClusterByPt = ptorder - clusterMaker.ClusterCorrectionTools += [ clusterCalibrator ] - clusterMaker += clusterCalibrator - - # done - return clusterMaker + ''' Configure name for calibration tool + ''' + towerCalName = towerCoreName+'Calibrator' + towerCalibrator = CaloTopoClusterFromTowerCalibrator(towerCalName) + mlog.info('add LCW calibration tool <'+towerCalName+'>') + mlog.info('TopoTowers: '+towerCalName+'.CellClusterWeightKey = "'+towerBuilder.CellClusterWeightKey+'"') + towerCalibrator.CellClusterWeightKey = towerBuilder.CellClusterWeightKey + towerCalibrator.OrderClusterByPt = configDict['OrderClusterByPt'] + if debugOn: + towerCalibrator.OutputLevel = Lvl.DEBUG + ''' Schedule calibration tool + ''' + towerMaker.ClusterCorrectionTools += [ towerCalibrator ] + towerMaker += towerCalibrator + + ####################### + # Configuration done ## + ####################### + + return towerMaker + +## +## toolname = configDict['ClusterBuilderName'] ### name of the tower builder tool +## cellkey = configDict['CaloCellContainerKey'] ### cell container key +## buildtopotower = configDict['BuildTopoTowers'] ### controls if topo-towers or inclusive towers are built +## towergeosvc = configDict['CaloTowerGeometrySvc'] ### tower geometry provider +## if ( buildtopotower ): +## topoclusterkey = configDict['CaloTopoClusterContainerKey'] +## else: +## topoclusterkey = 'N/A' +## +## cellweightkey = configDict['CellClusterWeightKey'] +## +## mlog.info('(input) CaloCellContainer <'+cellkey+'>') +## mlog.info('(input) CaloTopoClusterContainer <'+topoclusterkey+'>') +## mlog.info('(input) CellClusterWeightKey <'+cellweightkey+'>') diff --git a/Calorimeter/CaloRec/share/CaloRec_jobOptions.py b/Calorimeter/CaloRec/share/CaloRec_jobOptions.py index de9da525e1346511f3fee547907118882a33ca95..100a5278e0f7c6607d8037b36ee26899478bc003 100644 --- a/Calorimeter/CaloRec/share/CaloRec_jobOptions.py +++ b/Calorimeter/CaloRec/share/CaloRec_jobOptions.py @@ -248,14 +248,14 @@ else: # # functionality : Noise suppressed tower # -if jobproperties.CaloRecFlags.doCaloTopoTower() and DetFlags.haveRIO.Calo_on(): - try: - include ("CaloRec/CaloTopoTower_jobOptions.py") - except Exception: - treatException("Problem with CaloTopoTower. Switched off.") - jobproperties.CaloRecFlags.doCaloTopoTower=False -else: - jobproperties.CaloRecFlags.doCaloTopoTower=False +#if jobproperties.CaloRecFlags.doCaloTopoTower() and DetFlags.haveRIO.Calo_on(): +# try: +# include ("CaloRec/CaloTopoTower_jobOptions.py") +# except Exception: +# treatException("Problem with CaloTopoTower. Switched off.") +# jobproperties.CaloRecFlags.doCaloTopoTower=False +#else: +# jobproperties.CaloRecFlags.doCaloTopoTower=False # # functionality : muon candidates in Tile @@ -361,3 +361,10 @@ if rec.doWritexAOD(): #L1Calo Trigger tower decoration if globalflags.DataSource()=='data' and rec.doESD() and rec.doCalo() and rec.doTrigger(): include("TrigT1CaloCalibTools/DecorateL1CaloTriggerTowers_prodJobOFragment.py") + +#new style CaloTopoTowers +if jobproperties.CaloRecFlags.doCaloTopoTower(): + include ( "CaloRec/CaloTopoTowerFragment.py" ) +#mixed topo-cluster/topo-tower +if jobproperties.CaloRecFlags.doCaloTopoSignal(): + include ("CaloRec/CaloTopoSignalFragment.py" ) diff --git a/Calorimeter/CaloRec/share/CaloTopoSignalFragment.py b/Calorimeter/CaloRec/share/CaloTopoSignalFragment.py new file mode 100644 index 0000000000000000000000000000000000000000..5e936582044478363aab955eff6ba93da427ad18 --- /dev/null +++ b/Calorimeter/CaloRec/share/CaloTopoSignalFragment.py @@ -0,0 +1,65 @@ +###################################### +## Create standard 0.1 x 0.1 towers ## +###################################### + + +from AthenaCommon.Logging import logging +mlog = logging.getLogger('CaloTopoSognalFragment.py:: ') + +import AthenaCommon.Constants as Lvl +from AthenaCommon.AppMgr import ServiceMgr as svcMgr + +from CaloRec.MakeClustersFromTowers import ClustersFromTowersDict, MakeClustersFromTowers +from CaloRec.CaloRecConf import CaloTowerGeometrySvc, CaloTopoClusterTowerMerger + +mlog.info(' ') +mlog.info('##################################') +mlog.info('## Topological Signal Formation ##') +mlog.info('##################################') +mlog.info(' ') + +############################# +## Tower Geometry Provider ## +############################# + +if not hasattr(svcMgr,'CaloTowerGeometryProvider'): + mlog.info("setting up tower geometry provider") + caloTowerGeoSvc = CaloTowerGeometrySvc('CaloTowerGeometryProvider') + caloTowerGeoSvc.TowerEtaBins = 100 + caloTowerGeoSvc.TowerEtaMin = -5. + caloTowerGeoSvc.TowerEtaMax = 5. + svcMgr += caloTowerGeoSvc + + +############################# +## CaloTopoTower Formation ## +############################# + +caloTowerDict = ClustersFromTowersDict(clusterBuilderName='CaloFwdTopoTowerBuilder', + towerGeometrySvc=svcMgr.CaloTowerGeometryProvider, + cellContainerKey='AllCalo', + buildTopoTowers=True, + topoClusterContainerKey='CaloCalTopoClusters', + cellClusterWeightKey='CaloCalFwdTopoTowerCellWeights', + orderClusterByPt=False, + applyCellEnergyThreshold=False, + doCellIndexCheck=False, + cellEnergyThreshold=0., + applyLCW=True, + buildCombinedSignal=True, + clusterRange=2.5) + +caloTowerAlgo = MakeClustersFromTowers(towerMakerName = 'CaloFwdTopoTowerMaker', + towerContainerKey = 'CaloCalFwdTopoTowers', + configDict = caloTowerDict, + debugOn = False) +#merging +caloTowerMerger = CaloTopoClusterTowerMerger("CaloTopoSignalMaker") +caloTowerMerger.TopoClusterRange = caloTowerAlgo.CaloFwdTopoTowerBuilder.TopoClusterRange +caloTowerMerger.TopoClusterContainerKey = caloTowerAlgo.CaloFwdTopoTowerBuilder.CaloTopoClusterContainerKey +caloTowerMerger.TopoTowerContainerKey = caloTowerAlgo.ClustersOutputName +caloTowerMerger.TopoSignalContainerKey = 'CaloCalTopoSignals' +caloTowerMerger.OutputLevel = Lvl.DEBUG + +topSequence+=caloTowerAlgo +topSequence+=caloTowerMerger diff --git a/Calorimeter/CaloRec/share/CaloTopoTowerFragment.py b/Calorimeter/CaloRec/share/CaloTopoTowerFragment.py new file mode 100644 index 0000000000000000000000000000000000000000..56abf8c621187e77f2187bc65d939d3c759e8082 --- /dev/null +++ b/Calorimeter/CaloRec/share/CaloTopoTowerFragment.py @@ -0,0 +1,56 @@ +###################################### +## Create standard 0.1 x 0.1 towers ## +###################################### + + +from AthenaCommon.Logging import logging +mlog = logging.getLogger('CaloTopoTowerFragment.py:: ') + +import AthenaCommon.Constants as Lvl +from AthenaCommon.AppMgr import ServiceMgr as svcMgr + +from CaloRec.MakeClustersFromTowers import ClustersFromTowersDict, MakeClustersFromTowers +from CaloRec.CaloRecConf import CaloTowerGeometrySvc + +mlog.info(' ') +mlog.info('##################################') +mlog.info('## Standard Tower Configuration ##') +mlog.info('##################################') +mlog.info(' ') + +############################# +## Tower Geometry Provider ## +############################# + +if not hasattr(svcMgr,'CaloTowerGeometryProvider'): + mlog.info("setting up tower geometry provider") + caloTowerGeoSvc = CaloTowerGeometrySvc('CaloTowerGeometryProvider') + caloTowerGeoSvc.TowerEtaBins = 100 + caloTowerGeoSvc.TowerEtaMin = -5. + caloTowerGeoSvc.TowerEtaMax = 5. + svcMgr += caloTowerGeoSvc + +############################# +## CaloTopoTower Formation ## +############################# + +caloTowerDict = ClustersFromTowersDict(clusterBuilderName='CaloTopoTowerBuilder', + towerGeometrySvc=svcMgr.CaloTowerGeometryProvider, + cellContainerKey='AllCalo', + buildTopoTowers=True, + topoClusterContainerKey='CaloCalTopoClusters', + cellClusterWeightKey='CaloCalTopoTowerCellWeights', + orderClusterByPt=False, + applyCellEnergyThreshold=False, + doCellIndexCheck=False, + cellEnergyThreshold=0., + applyLCW=True, + buildCombinedSignal=False, + clusterRange=5.) + +caloTowerAlgo = MakeClustersFromTowers(towerMakerName = 'CaloTopoTowerMaker', + towerContainerKey = 'CaloCalTopoTowers', + configDict = caloTowerDict, + debugOn = False) + +topSequence+=caloTowerAlgo diff --git a/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.cxx b/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.cxx index 7b80840b591317c65e1903bf01bdcd92a6cfcedb..bdf1d6d8c7fea57daa37ba28b38bf744f80b4ad9 100644 --- a/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.cxx +++ b/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.cxx @@ -40,6 +40,7 @@ #include <cstdint> #include <limits> #include <math.h> +//#include <cstdio> using HepGeom::Vector3D; @@ -375,20 +376,22 @@ StatusCode CaloClusterMomentsMaker::execute(xAOD::CaloClusterContainer *theClusC // loop over all cell members and fill cell vector for used cells xAOD::CaloCluster::cell_iterator cellIter = theCluster->cell_begin(); xAOD::CaloCluster::cell_iterator cellIterEnd = theCluster->cell_end(); + // printf("CaloClusterMomentMaker::execute(...) - number of cells cluster %4i is %zu\n",iClus,theCluster->size()); + // int iCell(0); for(; cellIter != cellIterEnd; cellIter++ ){ - CxxUtils::prefetchNext(cellIter, cellIterEnd); + CxxUtils::prefetchNext(cellIter, cellIterEnd); const CaloCell* pCell = *cellIter; - - Identifier myId = pCell->ID(); - IdentifierHash myHashId = m_calo_id->calo_cell_hash(myId); - if ( clusterIdx[(unsigned int)myHashId].first != noCluster) { - // check weight and assign to current cluster if weight is > 0.5 - double weight = cellIter.weight(); - if ( weight > 0.5 ) + // printf("CaloClusterMomentMaker::execute(...) - cell %4i/%4zu reference %p\n",++iCell,theCluster->size(),(void*)pCell); + if ( pCell != 0 ) { + Identifier myId = pCell->ID(); + IdentifierHash myHashId = m_calo_id->calo_cell_hash(myId); + if ( clusterIdx[(unsigned int)myHashId].first != noCluster) { + // check weight and assign to current cluster if weight is > 0.5 + double weight = cellIter.weight(); + if ( weight > 0.5 ) clusterIdx[(unsigned int)myHashId].first = iClus; + } else { clusterIdx[(unsigned int)myHashId].first = iClus; - } - else { - clusterIdx[(unsigned int)myHashId].first = iClus; + } } } ++iClus; diff --git a/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerCalibrator.cxx b/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerCalibrator.cxx index 4a7c082f7420d3140da8abb728c82cd6522f3213..c75e4053aabb4e92aa9b3dacef043305f183d58c 100644 --- a/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerCalibrator.cxx +++ b/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerCalibrator.cxx @@ -1,9 +1,12 @@ /* Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration */ + #include "CaloRec/CaloTopoClusterFromTowerCalibrator.h" #include "CaloRec/CaloTopoClusterFromTowerHelpers.h" #include "CaloEvent/CaloCellClusterWeights.h" +#include "CaloGeoHelpers/CaloSampling.h" + #include <numeric> namespace { ///////////////////////////////////////////////////////////// @@ -16,24 +19,30 @@ namespace { } } -std::string CaloTopoClusterFromTowerCalibrator::m_defaultKey = "NONE"; - CaloTopoClusterFromTowerCalibrator::CaloTopoClusterFromTowerCalibrator(const std::string& type,const std::string& name,const IInterface* pParent) : AthAlgTool(type,name,pParent) - , m_cellClusterWeightsKey(m_defaultKey) + , m_cellClusterWeightKey("CaloTopoClusterCellWeights") , m_orderByPt(false) { declareInterface<CaloClusterCollectionProcessor>(this); - declareProperty("CellClusterWeightKey",m_cellClusterWeightsKey,"SG Key for CellClusterWeights (input)"); - declareProperty("OrderClusterByPt", m_orderByPt, "Order clusters by calibrated Pt (input)"); + declareProperty("CellClusterWeightKey",m_cellClusterWeightKey,"SG Key for CellClusterWeights (input)"); + declareProperty("OrderClusterByPt", m_orderByPt, "Order clusters by calibrated Pt (input)"); } +StatusCode CaloTopoClusterFromTowerCalibrator::initialize() +{ + ATH_CHECK(m_cellClusterWeightKey.initialize()); + return StatusCode::SUCCESS; +} StatusCode CaloTopoClusterFromTowerCalibrator::execute(xAOD::CaloClusterContainer* pClusCont) { // retrieve weights - const CaloCellClusterWeights* pCellWeights = 0; - CHECK(evtStore()->retrieve(pCellWeights,CaloCellClusterWeights::key(m_cellClusterWeightsKey) )); // PA change + SG::ReadHandle<CaloCellClusterWeights> pCellWeights(m_cellClusterWeightKey); + if ( !pCellWeights.isValid() ) { + ATH_MSG_ERROR( "Cannot allocate CaloCellClusterWeights with key <" << m_cellClusterWeightKey.key() << ">" ); + return StatusCode::FAILURE; + } ///////////////////////// // Calibrated clusters // @@ -46,7 +55,15 @@ StatusCode CaloTopoClusterFromTowerCalibrator::execute(xAOD::CaloClusterContaine const CaloCellClusterWeights::weight_t& wght(pCellWeights->at(*fCell)); // Retrieve list of weights associated with this cluster. // double weight(fCell.weight()); // Get cell-in-tower weight. // weight *= accumulateWeight(wght); // Combine with calibration weights. // - pClus->reweightCell(fCell,weight); // Set new weight. // + if ( weight == 0. ) { + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("[NO_LCW_REWEIGHT] Tower (%6.3f,%6.3f) cell [%6zu] weight = %6.3f [# LCW weights %zu geo %6.3f LCW %6.3f] SamplingID %2u Name \042%s\042", + pClus->eta(),pClus->phi(),(size_t)fCell->caloDDE()->calo_hash(),weight,wght.size(),fCell.weight(),weight/std::max(fCell.weight(),1e-08), + (unsigned int)fCell->caloDDE()->getSampling(),CaloSampling::getSamplingName(fCell->caloDDE()->getSampling()).c_str()) ); + } else { + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("[DO_LCW_REWEIGHT] Tower (%6.3f,%6.3f) cell [%6zu] weight = %6.3f [# LCW weights %zu geo %6.3f LCW %6.3f]", + pClus->eta(),pClus->phi(),(size_t)fCell->caloDDE()->calo_hash(),weight,wght.size(),fCell.weight(),weight/fCell.weight()) ); + pClus->reweightCell(fCell,weight); // Set new weight. // + } } //////////////////////////////////////////////////////////// // preserve raw (EM) kinematics double rawE(pClus->e()); //////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerMaker.cxx b/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerMaker.cxx index 2ef79a197b00eda28935230512d108ad6ea85212..bb4fa41e25257d1de7b3db657191bcbbb1f17616 100644 --- a/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerMaker.cxx +++ b/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerMaker.cxx @@ -1,14 +1,15 @@ -/* Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration */ +/* Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/SystemOfUnits.h" + +#include "AthenaKernel/Units.h" + #include "CaloRec/CaloTopoClusterFromTowerMaker.h" #include "CaloRec/CaloTopoClusterFromTowerHelpers.h" - -#include "xAODCaloEvent/CaloTower.h" -#include "xAODCaloEvent/CaloTower.h" #include "xAODCaloEvent/CaloClusterKineHelper.h" #include "CaloEvent/CaloClusterCellLink.h" -#include "CaloEvent/CaloCellTowerLink.h" #include "CaloEvent/CaloCellClusterWeights.h" #include "CaloGeoHelpers/CaloSampling.h" @@ -16,277 +17,280 @@ #include "CaloGeoHelpers/proxim.h" #include "CaloRec/CaloProtoCluster.h" +#include "CaloRec/CaloTowerGeometrySvc.h" + +#include "CaloDetDescr/CaloDetDescrElement.h" +#include "CaloDetDescr/CaloDetDescrManager.h" #include <algorithm> #include <cstdio> +#include <cstdarg> #include <string> #include <cmath> -#include <array> #include <memory> #include <vector> +#include <atomic> +#include <tuple> -////////////////////////////////////////////////// -// CaloTopoClusterFromTowerMaker::CellPathology // -////////////////////////////////////////////////// - -CaloTopoClusterFromTowerMaker::CellPathology::CellPathology() -{ } - -void CaloTopoClusterFromTowerMaker::CellPathology::setInvalidPointer(int cellhash,const CaloCell* cptr) -{ - std::string msg(CaloRec::Helpers::fmtMsg("CaloCell [%06i] has invalid pointer %p",cellhash,(void*)cptr)); - _addMsg(msg,_invalidPointer); +namespace { + MsgStream& operator<<(MsgStream& mstr,const SG::ReadHandleKey<CaloCellContainer>& ckey) { mstr << ckey.key(); return mstr; } + MsgStream& operator<<(MsgStream& mstr,const SG::ReadHandleKey<xAOD::CaloClusterContainer>& ckey) { mstr << ckey.key(); return mstr; } + MsgStream& operator<<(MsgStream& mstr,const SG::WriteHandleKey<CaloCellClusterWeights>& ckey) { mstr << ckey.key(); return mstr; } } -void CaloTopoClusterFromTowerMaker::CellPathology::setInvalidHash(int cellhash,const CaloCell* cptr) -{ - std::string msg(CaloRec::Helpers::fmtMsg("CaloCell [%06i] at %p has invalid hash %i",cellhash,(void*)cptr,cellhash)); - _addMsg(msg,_invalidHash); -} - -void CaloTopoClusterFromTowerMaker::CellPathology::setInvalidSampling(int cellhash,const CaloCell* cptr) -{ - int hash(CaloSampling::Unknown); - if ( cptr != 0 ) { hash = (int)cptr->caloDDE()->getSampling(); } - std::string msg(CaloRec::Helpers::fmtMsg("CaloCell [%06i] at %p has invalid sampling %2i (not in [0,%2i]",cellhash,(void*)cptr,hash,(int)CaloSampling::Unknown)); - _addMsg(msg,_invalidSampling); -} +std::atomic<bool> CaloTopoClusterFromTowerMaker_checkCellIndices(false); /////////////////////////////////// // CaloTopoClusterFromTowerMaker // /////////////////////////////////// -double CaloTopoClusterFromTowerMaker::m_energyThresholdDef = -100000000.; // in MeV -std::string CaloTopoClusterFromTowerMaker::m_defaultKey = "NONE"; +double CaloTopoClusterFromTowerMaker::m_energyThresholdDef = -100000000.; // in MeV +double CaloTopoClusterFromTowerMaker::m_clusterRangeDef = 5.; +std::string CaloTopoClusterFromTowerMaker::m_defaultKey = "NONE"; +CaloTopoClusterFromTowerMaker::uint_t CaloTopoClusterFromTowerMaker::m_errorValueUINT = uint_t(-1); CaloTopoClusterFromTowerMaker::CaloTopoClusterFromTowerMaker(const std::string& type, const std::string& name, const IInterface* pParent) : AthAlgTool(type,name,pParent) - , m_towerContainerKey(m_defaultKey) - , m_cellTowerLinksKey(m_defaultKey) + , m_towerGeometrySvc("CaloTowerGeometrySvc",name) + , m_clusterContainerKey("CaloTopoCluster") , m_cellContainerKey("AllCalo") - , m_clusterContainerKey(m_defaultKey) - , m_cellClusterWeightKey(m_defaultKey) + , m_cellClusterWeightKey("CaloTopoClusterCellWeights") , m_orderByPt(false) - , m_energyThreshold(m_energyThresholdDef-1.) - , m_applyLCW(false) - , m_applyEnergyThreshold(false) - , m_useCellsFromClusters(false) , m_prepareLCW(false) + , m_useCellsFromClusters(true) + , m_applyCellEnergyThreshold(false) + , m_doCellIndexCheck(false) + , m_buildCombinedSignal(false) + , m_energyThreshold(m_energyThresholdDef-1.) + , m_clusterRange(m_clusterRangeDef) , m_numberOfCells(0) - , m_numberOfSamplings(CaloSampling::Unknown) - , m_cellTowerLinksHandle(0) - , m_cellClusterWeights(0) + , m_maxCellHash(0) + , m_numberOfSamplings(static_cast<uint_t>(CaloSampling::Unknown)) + , m_numberOfTowers(0) { declareInterface<CaloClusterCollectionProcessor>(this); - declareProperty("CaloTowerContainerKey", m_towerContainerKey, "SG Key for CaloTowerContainer (input)"); - declareProperty("CaloCellContainerKey", m_cellContainerKey, "SG Key for CaloCellContainer (input)"); - declareProperty("CaloTopoClusterContainerKey", m_clusterContainerKey, "SG Key for CaloClusterContainer (input)"); - declareProperty("CellClusterWeightKey", m_cellClusterWeightKey,"SG Key for CellClusterWeights (output)"); - declareProperty("OrderClusterByPt", m_orderByPt, "Turn on/off pT-ordering of CaloClusterContainer (output)"); - declareProperty("CellEnergyThreshold", m_energyThreshold, "Energy threshold for cells filled in clusters"); - declareProperty("ApplyLCW", m_applyLCW, "Prepare data structure to apply LCW"); + declareProperty("CaloTowerGeometrySvc", m_towerGeometrySvc=ServiceHandle<CaloTowerGeometrySvc>("CaloTowerGeometrySvc",name), "Service providing tower geometry"); + declareProperty("CaloCellContainerKey", m_cellContainerKey, "SG Key for CaloCellContainer (input)"); + declareProperty("BuildTopoTowers", m_useCellsFromClusters, "Turn on/off topo-tower formation"); + declareProperty("CaloTopoClusterContainerKey", m_clusterContainerKey, "SG Key for CaloClusterContainer (input)"); + declareProperty("CellClusterWeightKey", m_cellClusterWeightKey, "SG Key for CellClusterWeights (output)"); + declareProperty("OrderClusterByPt", m_orderByPt, "Turn on/off pT-ordering of CaloClusterContainer (output)"); + declareProperty("ApplyCellEnergyThreshold", m_applyCellEnergyThreshold, "Turn on/off cell energy thresholds"); + declareProperty("CellEnergyThreshold", m_energyThreshold, "Energy threshold for cells filled in clusters"); + declareProperty("PrepareLCW", m_prepareLCW, "Prepare data structure to apply LCW"); + declareProperty("ExcludedSamplings", m_excludedSamplingsName, "Excluded samplings by name"); + 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"); } StatusCode CaloTopoClusterFromTowerMaker::initialize() { - // build SG key for cell-tower link map object - m_cellTowerLinksKey = m_towerContainerKey + CaloCellTowerLink::extTag; - ATH_MSG_INFO("Input retrieved from CaloTowerxAODContainer <" << m_towerContainerKey << "> and CaloCellTowerLink::Map <" << m_cellTowerLinksKey << ">"); - // check if energy threshold is to be applied - m_applyEnergyThreshold = m_energyThreshold > m_energyThresholdDef; - // check if filtered cells to be used - m_useCellsFromClusters = m_clusterContainerKey != m_defaultKey; - // analyze configuration + //--------------------// + // Set up handle keys // + //--------------------// + + ATH_CHECK(m_cellContainerKey.initialize()); + + //---------------------// + // Check configuration // + //---------------------// + + // tower geometry service + ATH_MSG_INFO("Allocate tower geometry service:"); + if ( !m_towerGeometrySvc.isValid() ) { + ATH_MSG_ERROR("[reject] cannot allocate tower geometry service - fatal"); + return StatusCode::FAILURE; + } else { + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("Tower geometry service is allocated, describes %6zu towers in grid:", m_towerGeometrySvc->towerBins()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("[accept] %3zu eta bins in [%5.2f,%5.2f]",m_towerGeometrySvc->etaBins(),m_towerGeometrySvc->etaMin(),m_towerGeometrySvc->etaMax()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("[accept] %3zu phi bins in [%5.2f,%5.2f]",m_towerGeometrySvc->phiBins(),m_towerGeometrySvc->phiMin(),m_towerGeometrySvc->phiMax()) ); + } + + // tower builder configurations if ( m_useCellsFromClusters ) { - if ( m_applyEnergyThreshold ) { - ATH_MSG_WARNING("Misconfiguration - cannot apply energy threshold to cells from TopoClusters, will accept all clustered cells"); - m_applyEnergyThreshold = false; - } else { - ATH_MSG_INFO("Filtered mode, cluster from towers filled with cells from TopoClusters"); + // topo-tower + ATH_MSG_INFO("Configure for building topo-towers (filtered mode):"); + // energy threshold not (yet) implemented for topo-towers + if ( m_applyCellEnergyThreshold ) { + ATH_MSG_WARNING("[ignore] cannot apply energy thresholds to topo-towers!"); + m_applyCellEnergyThreshold = false; } + ATH_CHECK(m_clusterContainerKey.initialize()); + // check on request for LCW + if ( m_prepareLCW ) { + ATH_CHECK(m_cellClusterWeightKey.initialize()); + ATH_MSG_INFO("[accept] prepare for LCW calibration - initialize CaloCellClusterWeights key object <" << m_cellClusterWeightKey << ">"); + } else { + ATH_MSG_INFO("[accept] use EM scale"); + } + } else { + // inclusive/exclusive towers + ATH_MSG_INFO("Configure for building cell towers:"); + if ( m_applyCellEnergyThreshold ) { + ATH_MSG_INFO("[accept] configure exclusive towers: use cell energy threshold"); + if ( m_energyThreshold < m_energyThresholdDef ) { + ATH_MSG_ERROR("######## [reject] invalid cell energy threshold " << m_energyThreshold/Athena::Units::GeV + << " GeV is smaller than default (no-op) " << m_energyThresholdDef/Athena::Units::GeV << " GeV - fatal"); + return StatusCode::FAILURE; + } + ATH_MSG_INFO("######## [accept] energy threshold for cells to contribute to towers is " << m_energyThreshold/Athena::Units::GeV << " GeV"); + } else { + ATH_MSG_INFO("[accept] configure inclusive towers"); + } // end inclusive/exclusive tower configuration + } // end tower builder configuration + + // local data (constant parameters) + m_numberOfCells = m_towerGeometrySvc->totalNumberCells(); + m_maxCellHash = m_towerGeometrySvc->maxCellHash(); + m_numberOfTowers = m_towerGeometrySvc->towerBins(); + ATH_MSG_INFO("Additional tool parameters:"); + if ( m_numberOfCells > 0 ) { + ATH_MSG_INFO("[accept] maximum cell hash index is " << m_maxCellHash); + ATH_MSG_INFO("[accept] maximum number of cells is " << m_numberOfCells); } else { - if ( m_applyEnergyThreshold ) { - ATH_MSG_INFO(CaloRec::Helpers::fmtMsg("Exclusive mode, cluster from towers filled with cells with energy > %.3f MeV",m_energyThreshold)); - } else { - ATH_MSG_INFO("Inclusive mode, all cells are used"); + ATH_MSG_ERROR("[reject] invalid maximum cell hash index/total number of cells " << m_maxCellHash << "/" << m_numberOfCells << " - fatal"); + return StatusCode::FAILURE; + } + if ( m_numberOfTowers > 0 ) { + ATH_MSG_INFO("[accept] maximum number of towers is " << m_numberOfTowers); + } else { + ATH_MSG_ERROR("[reject] invalid maximum number of towers " << m_numberOfTowers << " - fatal"); + return StatusCode::FAILURE; + } + + if ( m_excludedSamplingsName.empty() ) { + m_excludedSamplings.clear(); + m_excludedSamplingsPattern.reset(); + ATH_MSG_INFO("Cells from all samplings used for topo-cluster included"); + } else { + size_t nex(std::min(m_excludedSamplingsName.size(), m_excludedSamplingsPattern.size())); + if ( m_excludedSamplingsName.size() > m_excludedSamplingsPattern.size() ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Configuration problem: number of excluded sampling names %zu exceeds expected maximum %zu - ignore last %zu name(s)", + m_excludedSamplingsName.size(), m_excludedSamplingsPattern.size(),m_excludedSamplingsName.size()-m_excludedSamplingsPattern.size()) ); + } + m_excludedSamplings.resize(nex); + m_excludedSamplingsPattern.reset(); + for ( size_t i(0); i<nex; ++i ) { + m_excludedSamplings[i] = CaloRec::Lookup::getSamplingId(m_excludedSamplingsName.at(i)); + m_excludedSamplingsPattern.set(i); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("CaloSampling \042%10.10s\042 has id %2zu (name in lookup table \042%10.10s\042)", + m_excludedSamplingsName.at(i).c_str(),(size_t)m_excludedSamplings.at(i),CaloRec::Lookup::getSamplingName(m_excludedSamplings.at(i)).c_str()) ); } } - // build SG key for cell weight lookup - m_prepareLCW = m_applyLCW && m_useCellsFromClusters && ( m_cellClusterWeightKey != m_defaultKey ); - if ( m_prepareLCW ) { ATH_MSG_INFO("Prepare LCW calibration"); } - else { ATH_MSG_INFO("No preparation for LCW calibration"); } + + ATH_MSG_INFO("Other properties:"); + std::map<bool,std::string> blu { { true, "true" }, { false, "false" } }; + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("PrepareLCW ................. %s", blu[m_prepareLCW].c_str()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("BuildTopoTowers ............ %s", blu[m_useCellsFromClusters].c_str()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("ApplyCellEnergyThreshold ... %s", blu[m_applyCellEnergyThreshold].c_str()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("OrderClusterByPt ........... %s", blu[m_orderByPt].c_str()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("DoCellIndexCheck ........... %s", blu[m_doCellIndexCheck].c_str()) ); + 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()) ); return StatusCode::SUCCESS; } StatusCode CaloTopoClusterFromTowerMaker::finalize() +{ return StatusCode::SUCCESS; } + +StatusCode CaloTopoClusterFromTowerMaker::execute(xAOD::CaloClusterContainer* pClusCont) { - ATH_MSG_INFO(" "); - ATH_MSG_INFO("Summary of warnings in execute():"); - ATH_MSG_INFO("Count: Warning:"); - for ( auto fiter(m_warning.begin()); fiter!=m_warning.end(); ++fiter ) { - ATH_MSG_INFO(CaloRec::Helpers::fmtMsg("%6i \042%s\042",(int)fiter->second,fiter->first.c_str())); + ///////////////// + // Check input // + ///////////////// + + // CaloCellContainer is needed to construct CaloProtoCluster + SG::ReadHandle<CaloCellContainer> pCellCont(m_cellContainerKey); + if ( !pCellCont.isValid() ) { + ATH_MSG_ERROR("Cannot allocate CaloCellContainer with key <" << m_cellContainerKey << ">"); + return StatusCode::FAILURE; } - ATH_MSG_INFO(" "); - ATH_MSG_INFO("Summary of messages in execute():"); - ATH_MSG_INFO("Count: Message:"); - for ( auto fiter(m_message.begin()); fiter!=m_message.end(); ++fiter ) { - ATH_MSG_INFO(CaloRec::Helpers::fmtMsg("%6i \042%s\042",(int)fiter->second,fiter->first.c_str())); + if ( msgLvl(MSG::DEBUG) && m_numberOfCells != pCellCont->size() ) { + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("[mismatch] number of cells in CaloCellContainer %6zu, total number of cell descriptors %6zu", + pCellCont->size(),m_towerGeometrySvc->totalNumberCells()) ); } - if ( !m_cellProblems.invalidPointer().empty() ) { - ATH_MSG_INFO(" "); - ATH_MSG_INFO("Observed cell pathologies [invalid pointer]:"); - printProblems(m_cellProblems.invalidPointer()); - } - if ( !m_cellProblems.invalidHash().empty() ) { - ATH_MSG_INFO(" "); - ATH_MSG_INFO("Observed cell pathologies [invalid hash]:"); - printProblems(m_cellProblems.invalidHash()); - } - if ( !m_cellProblems.invalidSampling().empty() ) { - ATH_MSG_INFO(" "); - ATH_MSG_INFO("Observed cell pathologies [invalid sampling]:"); - printProblems(m_cellProblems.invalidSampling()); - } - ATH_MSG_INFO(" "); - - return StatusCode::SUCCESS; -} -StatusCode CaloTopoClusterFromTowerMaker::execute(xAOD::CaloClusterContainer* pClusCont) -{ - // find cell-tower links - CHECK(detStore()->retrieve(m_cellTowerLinksHandle,m_cellTowerLinksKey)); - - // find input: CaloCell container - const CaloCellContainer* pCellCont = 0; - CHECK(evtStore()->retrieve(pCellCont,m_cellContainerKey)); - m_numberOfCells = (int)pCellCont->size(); - - // cross check - this->addMessage(CaloRec::Helpers::fmtMsg("CaloCellContainer::%s size %i, CaloCellTowerlink::Map size %i", - m_cellContainerKey.c_str(),(int)pCellCont->size(),(int)m_cellTowerLinksHandle->size())); - for ( size_t itl(0); itl<m_cellTowerLinksHandle->size(); ++itl ) { - if ( itl >= pCellCont->size() ) { - this->addWarning(CaloRec::Helpers::fmtMsg("CaloCell [%06i] has hash out of reach (max hash is %i)",(int)itl,(int)pCellCont->size()-1)); - } else { - if ( pCellCont->at(itl) == 0 ) { this->addWarning(CaloRec::Helpers::fmtMsg("CaloCell [%06i] has invalid pointer",(int)itl)); } - } - } - // int icell(0); - // int ncell(0); - // for ( auto cptr : *pCellCont ) { printf("CaloCell [%06i/%06i] ptr = %p\n",icell++,m_numberOfCells,(void*)cptr); if ( cptr == 0 ) { ++ncell; } } - // this->addMessage(CaloRec::Helpers::fmtMsg("Allocated CaloCellContainer with key <%s> at %p",m_cellContainerKey.c_str(),(void*)pCellCont)); - - // find input: tower container - const xAOD::CaloTowerContainer* pTowCont = 0; - CHECK(evtStore()->retrieve(pTowCont,m_towerContainerKey)); - // this->addMessage(CaloRec::Helpers::fmtMsg("Allocated CaloTowerContainer with key <%s> at %p",m_towerContainerKey.c_str(),(void*)pTowCont)); - - ////////////////////////////////////////////////////////////////////////////////////////// - // Tricky bit: // - // Especially for fine tower grids some towers may have 0 energy - in particular if the // - // grid spans -5.0 < eta < 5.0. The proto-cluster container has the same size as the // - // tower container, so it will have empty proto-clusters. These are removed when the // - // proto-clusters are converted to full CaloCluster objects. The tower center in // - // (eta,phi) is preserved in eta0(), phi0() of the CaloCluster. The cluster container // - // index has no relation to the tower position anymore. // - ////////////////////////////////////////////////////////////////////////////////////////// + if ( m_doCellIndexCheck ) { this->checkCellIndices(pCellCont.cptr()); } ///////////////////////// // Set up ProtoCluster // ///////////////////////// - protocont_t pProtoCont(pTowCont->size(),(CaloProtoCluster*)0); - for ( size_t itow(0); itow<pTowCont->size(); ++itow) { pProtoCont[itow] = new CaloProtoCluster(pCellCont); } + // index of CaloProtoCluster in container relates to tower position! DO NOT sort, shuffle, or remove elements! + protocont_t pProtoCont; pProtoCont.reserve(m_numberOfTowers); + for ( uint_t i(0); i<m_numberOfTowers; ++i ) { pProtoCont.push_back(CaloProtoCluster(pCellCont.cptr())); } ////////////////////////////////////////////////////// // Apply overall cell filter and fill protoclusters // ////////////////////////////////////////////////////// - if ( m_useCellsFromClusters ) { /////////////////////////////////////////////////////// - // retrieve TopoCluster container // The weights extracted here are the cell signal // - const xAOD::CaloClusterContainer* pTopoClusCont = 0; // weights after LCW (typically)! These are products // - CHECK(evtStore()->retrieve(pTopoClusCont,m_clusterContainerKey)); // of the geometrical weight in cell splitting // - // instantiate cell-cluster link object // between clusters and the calibration weights. // - m_cellClusterWeights = new CaloCellClusterWeights(pCellCont->size()); // The geometrical weight of a cell in the towers is // - // fill the weights: cluster loop // used in the addCellToProtoCluster method. // - for ( auto pClus : *pTopoClusCont ) { /////////////////////////////////////////////////////// - // cell loop - for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) { - if ( !m_cellClusterWeights->check(*fCell) ) { this->addCellToProtoCluster(*fCell,pProtoCont); } // fill protocluster only once/cell - m_cellClusterWeights->set(*fCell,fCell.weight()); // prep for calibration tool - } // cell in cluster loop - } // cluster loop - // store LCW weights for calibrator - if ( m_prepareLCW ) { - CHECK(evtStore()->record(m_cellClusterWeights,CaloCellClusterWeights::key(m_cellClusterWeightKey))); - } else { - delete m_cellClusterWeights; m_cellClusterWeights = 0; - } + // The weights extracted for cells from clusters are LCW weights (typically). The total + // contribution of a LCW-weighted cell to towers is Ecell*Weight_LCW*Weight_tower. - ///////////////////////////////////////////////////////////// - // Generate and fill inclusive or exclusive proto-clusters // - ///////////////////////////////////////////////////////////// - - } else { - if ( !m_applyEnergyThreshold ) { buildInclClusters(*pCellCont,pProtoCont); } else { buildExclClusters(*pCellCont,pProtoCont); } - } + // If EM clusters are used, the weights of a clustered cell are completely defined + // by the tower grid. As cells can shared between clusters, each cell can only be + // projected onto the towergrid once, with Ecell*Weight_tower - //////////////////////////// - // Convert proto-clusters // - //////////////////////////// + // The CaloCellClusterWeights object is used to store the combined LCW weight. + // for each clustered cell. In case of EM, the LCW weights are ignored and this + // object is not used - a simple vector<bool> tags cells already put into towers. - pClusCont->reserve(pProtoCont.size()); - - xAOD::CaloCluster::ClusterSize csize = this->getClusterSize(*pTowCont); - int ictr(0); - for ( size_t ipc(0); ipc<pProtoCont.size(); ++ipc ) { - // auto fproto(pProtoCont.begin()); - // while ( fproto != pProtoCont.end() ) { - // CaloProtoCluster* pProto = *fproto; - CaloProtoCluster* pProto = pProtoCont.at(ipc); - if ( pProto != 0 ) { - CaloClusterCellLink* lptr = pProto->releaseCellLinks(); // take over CaloClusterCellLink object - // convert proto-cluster to cluster - if ( lptr->size() > 0 ) { // remove empty proto-clusters - xAOD::CaloCluster* clptr = new xAOD::CaloCluster(); // new empty cluster - pClusCont->push_back(clptr); // put into container - 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(pTowCont->eta(ipc)); // save the tower center eta - clptr->setPhi0(pTowCont->phi(ipc)); // save the tower center phi - ++ictr; // counts the number of CaloCluster produced in the end - } // tower has cells - delete pProto; // delete the proto-cluster object - pProtoCont[ipc] = (CaloProtoCluster*)0; // FIXME (needed?) - } // valid proto-cluster + uint_t cCtr(0); + if ( m_useCellsFromClusters ) { + // retrieve topo-cluster container for topo-towers + SG::ReadHandle<xAOD::CaloClusterContainer> pTopoClusCont(m_clusterContainerKey); + if ( !pTopoClusCont.isValid() ) { + ATH_MSG_ERROR("Cannot allocate xAOD::CaloClusterContainer with key <" << m_clusterContainerKey << ">"); + return StatusCode::FAILURE; + } // check on ReadHandle validity + cCtr = m_prepareLCW ? this->buildLCWTopoTowers(*pTopoClusCont,pProtoCont) : this->buildEMTopoTowers(*pTopoClusCont,pProtoCont); + if ( !isValidIndex(cCtr) ) { ATH_MSG_WARNING("problems building EM or LCW topo-towers"); return StatusCode::SUCCESS; } + } else { + // fill inclusive/exclusive towers + cCtr = m_applyCellEnergyThreshold ? this->buildExclTowers(*pCellCont,pProtoCont) : this->buildInclTowers(*pCellCont,pProtoCont); + if ( !isValidIndex(cCtr) ) { ATH_MSG_WARNING("problems building EM inclusive or exclusive towers"); return StatusCode::SUCCESS; } + } // end topo-towers/inclusive-exclusive towers + + // allocate sufficient space in vector + pClusCont->reserve(cCtr); + // pick up cluster size tag and set up counter + xAOD::CaloCluster::ClusterSize csize = this->getClusterSize(m_numberOfTowers); + // loop proto-clusters + for ( uint_t ipc(0); ipc<pProtoCont.size(); ++ipc ) { + CaloProtoCluster& pProto = pProtoCont.at(ipc); // pick up proto-cluster + CaloClusterCellLink* lptr = pProto.releaseCellLinks(); // take over CaloClusterCellLink object + this->cleanupCells(lptr,ipc); // clean up cell links + if ( this->filterProtoCluster(*lptr) ) { // ignore empty proto-clusters (no cells assigned) + xAOD::CaloCluster* clptr = new xAOD::CaloCluster(); // new empty cluster + pClusCont->push_back(clptr); // put into container + 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 + } else { + delete lptr; + } } // proto-cluster loop - pProtoCont.clear(); // clean up (objects in this container have already been destroyed) - - //////////////////// - // Check clusters // - //////////////////// - - size_t idc(0); - for ( auto pClus : *pClusCont ) { - if ( pClus->getCellLinks() == 0 || pClus->getCellLinks()->size() == 0 ) { - this->addWarning(CaloRec::Helpers::fmtMsg("Cluster #%05i has invalid pointer (%p) or no cells",idc,(void*)pClus)); - } - ++idc; - } + // clean up proto-cluster container + pProtoCont.clear(); - //////////////////////// - // Sort protoclusters // - //////////////////////// + ///////////// + // Sorting // + ///////////// - // definitively removes the index-to-tower center relation in all cases! + // All towers/clusters at this point are on EM scale. Sorting LCW towers by pT should be done in the + // CaloTopoClusterFromTowerCalibrator tool to assure desired ordering on the final scale. + // The link between tower location and index of tower representation (CaloCluster) in its + // container is definitively broken after sorting (was never ok in mixed cluster/tower mode). if ( m_orderByPt ) { std::sort(pClusCont->begin(),pClusCont->end(),[](xAOD::CaloCluster* pc1,xAOD::CaloCluster* pc2) { volatile double pt1(pc1->pt()); // FIXME needed? (this was just copied) @@ -294,226 +298,317 @@ StatusCode CaloTopoClusterFromTowerMaker::execute(xAOD::CaloClusterContainer* pC return ( pt1 > pt2 ); } ); + } // end ordered by pT + + return StatusCode::SUCCESS; +} // end execute + +////////////////////// +// Fill topo-towers // +////////////////////// + +// EM +CaloTopoClusterFromTowerMaker::uint_t CaloTopoClusterFromTowerMaker::buildEMTopoTowers(const xAOD::CaloClusterContainer& pClusCont,protocont_t& pProtoCont) +{ + // presets + uint_t cCtr(0); + std::vector<bool> cellTags(m_numberOfCells,false); + + // -- EM scale clusters + if ( !m_buildCombinedSignal ) { + // topo-towers + for ( auto pClus : pClusCont ) { + for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) { + uint_t cidx(static_cast<uint_t>((*fCell)->caloDDE()->calo_hash())); + if ( cidx < cellTags.size() ) { + if ( !cellTags.at(cidx) ) { cellTags[cidx] = this->addCellToProtoCluster(*fCell,pProtoCont); } + } else { + ATH_MSG_ERROR( CaloRec::Helpers::fmtMsg("Invalid cell hash index %6zu >= maximum index %6zu for cell in %s at (eta,phi) = (%6.3,%f6.3)", + cidx,cellTags.size(),CaloSampling::getSamplingName((*fCell)->caloDDE()->getSampling()).c_str(),(*fCell)->eta(),(*fCell)->phi()) ); + return m_errorValueUINT; + } + } // end cells-in-cluster loop + } // end cluster loop + } else { + // selected topo-towers for combined signal + std::vector<std::tuple<const CaloCell*,double> > cellList(m_numberOfCells,std::tuple<const CaloCell*,double>(0,0.)); + for ( auto pClus : pClusCont ) { + if ( std::abs(pClus->eta()) > m_clusterRange ) { + for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) { + uint_t cidx(static_cast<uint_t>((*fCell)->caloDDE()->calo_hash())); + if ( cellTags.at(cidx) ) { + std::get<1>(cellList[cidx]) += fCell.weight(); + } else { + cellList[cidx] = std::tuple<const CaloCell*,double>(*fCell,fCell.weight()); + cellTags[cidx] = true; + } + } // cell in cluster loop + } else { + ++cCtr; + } // cluster range check + } // cluster loop + // fill proto-cluster + for ( auto tpl : cellList ) { this->addCellToProtoCluster(std::get<0>(tpl),pProtoCont,std::get<1>(tpl)); } + } // end of fill mode + + // + return cCtr+pProtoCont.size(); +} + +// LCW +CaloTopoClusterFromTowerMaker::uint_t CaloTopoClusterFromTowerMaker::buildLCWTopoTowers(const xAOD::CaloClusterContainer& pClusCont,protocont_t& pProtoCont) +{ + // Need to keep track of LCW weights (up to two per cell) available from the topo-cluster(s) the cell is assigned to. + // Each cell in a topo-cluster is, at first occurance, added to the CaloProtoCluster(s) representing the tower(s) and its + // LCW calibration weight is stored in a lookup table indexed by the calorimeter hash id of the cell. The second + // time the same cell is found in another topo-cluster, only its LCW weight is added to the lookup table (stored in + // CaloCellClusterWeights for use in the downstream tower calibration tool) - the assignment to tower(s) has already + // happened. + + uint_t cCtr(0); + // write handle object on the stack + SG::WriteHandle<CaloCellClusterWeights> cellClusterWeightHandle(m_cellClusterWeightKey); + // record output container + if ( cellClusterWeightHandle.record(std::make_unique<CaloCellClusterWeights>(m_towerGeometrySvc->maxCellHash())).isFailure() ) { + ATH_MSG_WARNING( "Cannot record cluster cell weights with key <" << m_cellClusterWeightKey << ">" ); + return m_errorValueUINT; } + // project cells on tower grid + if ( !m_buildCombinedSignal ) { + for ( auto pClus : pClusCont ) { + for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) { + // map to towers only once + if ( !cellClusterWeightHandle.ptr()->check(*fCell) ) { this->addCellToProtoCluster(*fCell,pProtoCont); } + // store all associated LCW weights + cellClusterWeightHandle.ptr()->set(*fCell,fCell.weight()); + } // end cells-in-cluster loop + } // end cluster loop + } else { + for ( auto pClus : pClusCont ) { + if ( std::abs(pClus->eta()) > m_clusterRange ) { + for ( auto fCell(pClus->cell_begin()); fCell != pClus->cell_end(); ++fCell ) { + // map to towers only once + if ( !cellClusterWeightHandle.ptr()->check(*fCell) ) { this->addCellToProtoCluster(*fCell,pProtoCont); } + // store all associated LCW weights + cellClusterWeightHandle.ptr()->set(*fCell,fCell.weight()); + } // end cells-in-cluster loop + } else { + ++cCtr; + } // end range check + } // end cluster loop + } // end combined signal check + + // + return cCtr+pProtoCont.size(); +} + +///////////////// +// Fill towers // +///////////////// +// inclusive +CaloTopoClusterFromTowerMaker::uint_t CaloTopoClusterFromTowerMaker::buildInclTowers(const CaloCellContainer& pCellCont,protocont_t& pProtoCont) +{ + // loop cell container - counter icl replaces cell hash index for NULL pointers in cell container + uint_t icl(0); + for ( auto cptr : pCellCont ) { + if ( cptr == 0 ) { + ATH_MSG_ERROR( CaloRec::Helpers::fmtMsg("CaloCellContainer[%6zu] contains invalid cell object pointer %p",icl,(void*)cptr) ); + return m_errorValueUINT; + } else { + // existing cell with non-zero energy (negative or positive) + if ( std::fabs(cptr->e()) > 0. ) { this->addCellToProtoCluster(cptr,pProtoCont); } + } // end pointer check + ++icl; + } // end cell loop + return pProtoCont.size(); +} + +// exclusive +CaloTopoClusterFromTowerMaker::uint_t CaloTopoClusterFromTowerMaker::buildExclTowers(const CaloCellContainer& pCellCont,protocont_t& pProtoCont) +{ + // loop cell container + uint_t icl(0); + for ( auto cptr : pCellCont ) { + if ( cptr == 0 ) { + ATH_MSG_ERROR( CaloRec::Helpers::fmtMsg("CaloCellContainer[%6zu] contains invalid cell object pointer %p",icl,(void*)cptr) ); + return m_errorValueUINT; + } else { + // existing cell with energy above threshold + if ( cptr->e() > m_energyThreshold ) { this->addCellToProtoCluster(cptr,pProtoCont); } + } // end pointer check + ++icl; + } // end cell loop return StatusCode::SUCCESS; } -xAOD::CaloCluster::ClusterSize CaloTopoClusterFromTowerMaker::getClusterSize(const xAOD::CaloTowerContainer& towerCont) +bool CaloTopoClusterFromTowerMaker::addCellToProtoCluster(const CaloCell* cptr,protocont_t& pProtoCont,double weight) { - return towerCont.nTowers() == 6400 - ? xAOD::CaloCluster::Tower_01_01 : towerCont.nTowers() == 25600 - ? xAOD::CaloCluster::Tower_005_005 : xAOD::CaloCluster::CSize_Unknown; + // invalid input + if ( cptr == 0 ) { return false; } + + // get towers for cell from geometry service + uint_t nctr(0); + for ( auto elm : m_towerGeometrySvc->getTowers(cptr) ) { + auto towerIdx(m_towerGeometrySvc->towerIndex(elm)); + if ( !m_towerGeometrySvc->isInvalidIndex(towerIdx) ) { + if ( !m_excludedSamplingsPattern[(size_t)cptr->caloDDE()->getSampling()] ) { + uint_t cellIdx(pProtoCont.at(towerIdx).getCellLinks()->getCellContainer()->findIndex(cptr->caloDDE()->calo_hash())); + pProtoCont[towerIdx].addCell(cellIdx,m_towerGeometrySvc->cellWeight(elm)*weight); ++nctr; + } + } + } + return nctr > 0; +} + +///////////// +// Helpers // +///////////// + +xAOD::CaloCluster::ClusterSize CaloTopoClusterFromTowerMaker::getClusterSize(uint_t etaBins,uint_t phiBins) +{ return this->getClusterSize(etaBins*phiBins); } + +xAOD::CaloCluster::ClusterSize CaloTopoClusterFromTowerMaker::getClusterSize(uint_t nTowers) +{ + // check for tower sizes + return nTowers == 6400 // known "standard" towers 0,1 x 0.1 + ? xAOD::CaloCluster::Tower_01_01 + : nTowers == 25600 // known "fine" towers 0.05 x 0.05 + ? xAOD::CaloCluster::Tower_005_005 + : xAOD::CaloCluster::Tower_fixed_area; // unspecified towers } -int CaloTopoClusterFromTowerMaker::cleanupCells(CaloClusterCellLink* clk) +int CaloTopoClusterFromTowerMaker::cleanupCells(CaloClusterCellLink* clk,uint_t nclus) { + // Any pathology here probably indicates a configuration problem with the conditions (geometry) + // database (wrong tag for data?) + // check on null pointers in cell links int nrc(0); int hid(0); auto fcell(clk->begin()); while ( fcell != clk->end() ) { const CaloCell* pCell = *fcell; - this->addMessage(CaloRec::Helpers::fmtMsg("CaloCell* = %p in CaloClusterCellLink* = %p")); - bool removeCell(false); - if ( pCell == 0 ) { - m_cellProblems.setInvalidPointer(hid,pCell); - removeCell = true; + auto nc(clk->getCellContainer()->size()); + const CaloCell* aCell = fcell.index() < nc ? clk->getCellContainer()->at(fcell.index()) : (const CaloCell*)0; + if ( pCell == 0 ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("CaloCellContainer[%6zu/%6zu] - tower %5zu at (%6.3f,%6.3f) - cell pointer invalid (%p/%p) [removed %3i of %3zu cells]", + fcell.index(),nc-1,nclus,m_towerGeometrySvc->towerEta(nclus),m_towerGeometrySvc->towerPhi(nclus), + (void*)pCell,(void*)aCell,++nrc,clk->size()) ); + fcell = clk->removeCell(fcell); } else { - int hash((int)pCell->caloDDE()->calo_hash()); - if ( hash >= m_numberOfCells ) { m_cellProblems.setInvalidHash(hash,pCell); removeCell = true; } - int samp((int)pCell->caloDDE()->getSampling()); - if ( samp >= m_numberOfSamplings ) { m_cellProblems.setInvalidSampling(hash,pCell); removeCell = true; } - } - if ( removeCell ) { fcell = clk->removeCell(fcell); ++nrc; } else { ++fcell; } + uint_t chash(static_cast<uint_t>(pCell->caloDDE()->calo_hash())); + uint_t csamp(static_cast<uint_t>(pCell->caloDDE()->getSampling())); + if (chash > m_maxCellHash ) { + // check cell hash + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Tower %5zu at (%6.3f,%6.3f) linked cell %3i - cell hash index (%6zu/%6zu) invalid", + nclus,m_towerGeometrySvc->towerEta(nclus),m_towerGeometrySvc->towerPhi(nclus),hid,chash,m_maxCellHash) ); + fcell = clk->removeCell(fcell); ++nrc; + } else if ( csamp >= m_numberOfSamplings ) { + // check sampling id + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Tower %5zu at (%6.3f,%6.3f) linked cell %3i -cell sampling id (%3zu/%3zu) invalid", + nclus,m_towerGeometrySvc->towerEta(nclus),m_towerGeometrySvc->towerPhi(nclus),hid,csamp,m_numberOfSamplings) ); + fcell = clk->removeCell(fcell); ++nrc; + } else if ( fcell.weight() <= 0.0000001 ) { + // remove cells with 0 weight + fcell = clk->removeCell(fcell); ++nrc; + } else { + // next cell + ++fcell; + } + } // end remove cell due to pointer invalid ++hid; - } + } // end loop on cells in cell link object return nrc; } -// bool CaloTopoClusterFromTowerMaker::calculateKine(xAOD::CaloCluster* pClus) -// { return CaloRec::Helpers::updateKine -// // input -// if ( pClus == 0 ) { -// ATH_MSG_WARNING("Invalid (NULL) pointer to xAOD::CaloCluster object"); -// return false; -// } -// // copy from CaloKineHelper::calculateKine(...) - but without the prefetch! -// const CaloClusterCellLink* clk = pClus->getCellLinks(); -// if ( clk == 0 ) { -// this->addWarning(CaloRec::Helpers::fmtMsg("Invalid reference (pointer %p) to CaloClusterCellLink object",(void*)clk)); -// return false; -// } -// if ( clk->size() == 0 ) { -// this->addWarning(CaloRec::Helpers::fmtMsg("Number of linked cells in cluster is %i",(int)clk->size())); -// return false; -// } - -// // accumulator object -// CaloRec::Helpers::CaloClusterSignalAccumulator accum; -// // accumulate cells -// for ( auto cIter(clk->begin()); cIter!=clk->end(); ++cIter) { -// const CaloCell* pCell = *cIter; -// if ( pCell != 0 ) { -// if ( !CaloRec::Helpers::caloCellAccumulator(*pCell,accum,cIter.weight(),false) ) { -// this->addWarning(CaloRec::Helpers::fmtMsg("CaloCell [%06i] has invalid sampling id %2i (not in [0,%2i])",(int)(*cIter)->caloDDE()->calo_hash(),(int)(*cIter)->caloDDE()->getSampling(),(int)CaloSampling::Unknown)); -// } -// } else { -// this->addWarning(CaloRec::Helpers::fmtMsg("Unexpected CaloCell pointer %p detected",(void*)pCell)); -// } -// } - -// // set cluster kinematics: energy & mass -// pClus->setE(accum.cluster.accumE); -// pClus->setM(0.); - -// // set cluster kinematics: directions -// if ( accum.cluster.accumAbsE != 0. ) { -// double invPosNorm(1./accum.cluster.accumAbsE); -// pClus->setEta(accum.cluster.accumEta*invPosNorm); -// pClus->setPhi(CaloPhiRange::fix(accum.cluster.accumPhi*invPosNorm)); -// } else { -// pClus->setEta(0.); -// pClus->setPhi(0.); -// } - -// // set cluster kinematics: time -// if ( accum.cluster.accumTimeNorm != 0. ) { -// pClus->setTime(accum.cluster.accumTime/accum.cluster.accumTimeNorm); -// } else { -// pClus->setTime(0.); -// } - -// // set sampling pattern -// uint32_t samplingPattern(0); -// for ( int i(0); i<(int)CaloSampling::Unknown; ++i ) { -// if ( accum.sampling.presenceInSample[i] ) { samplingPattern |= (0x1U<<i); } -// if ( samplingPattern != pClus->samplingPattern() ) { -// pClus->clearSamplingData(); -// pClus->setSamplingPattern(samplingPattern,true); -// } -// } - -// // set sampling variables -// for ( int i(0); i<(int)CaloSampling::Unknown; ++i ) { -// if ( accum.presenceInSample[i] ) { -// CaloSampling::CaloSample sam = (CaloSampling::CaloSample)i; -// pClus->setEnergy(sam,accum.energyInSample[i]); -// if ( accum.posNormInSample[i] != 0. ) { -// pClus->setEta(sam,accum.etaInSample[i]/accum.posNormInSample[i]); -// pClus->setPhi(sam,accum.phiInSample[i]/accum.posNormInSample[i]); -// } else { -// pClus->setEta(sam,accum.etaInSample[i]); -// pClus->setPhi(sam,accum.phiInSample[i]); -// } -// pClus->setEmax(sam,accum.maxEnergyInSample[i]); -// pClus->setEtamax(sam,accum.etaMaxEnergyInSample[i]); -// pClus->setPhimax(sam,accum.phiMaxEnergyInSample[i]); -// } // check if sampling is in cluster -// } // loop on samplings - -// return true; -// } - -void CaloTopoClusterFromTowerMaker::addWarning(const std::string& msg) -{ - ATH_MSG_WARNING(msg); - auto fiter(m_warning.find(msg)); - if ( fiter == m_warning.end() ) { m_warning[msg] = 0; } - ++m_warning[msg]; -} +bool CaloTopoClusterFromTowerMaker::filterProtoCluster(const CaloClusterCellLink& clnk) const +{ return clnk.size() > 0; } -void CaloTopoClusterFromTowerMaker::addMessage(const std::string& msg) +bool CaloTopoClusterFromTowerMaker::checkCellIndices(const CaloCellContainer* pCellCont) const { - ATH_MSG_DEBUG(msg); - auto fiter(m_message.find(msg)); - if ( fiter == m_message.end() ) { m_message[msg] = 0; } - ++m_message[msg]; -} + //////////////////////////// + // input and setup checks // + //////////////////////////// -void CaloTopoClusterFromTowerMaker::printProblems(const std::map<std::string,int>& map) -{ - static std::string _dstr = "...................................................................."; - static size_t _lds = _dstr.length(); - static size_t _occ = _lds - 3; - // - for ( auto fmap(map.begin()); fmap!=map.end(); ++fmap ) { - std::string msg = fmap->first.length() > _occ ? fmap->first.substr(0,_occ) : fmap->first; - std::string prn(std::string(_dstr).replace(0,msg.length(),msg)); - ATH_MSG_INFO(CaloRec::Helpers::fmtMsg("%s %i",prn.c_str(),fmap->second)); + // check argument + if ( pCellCont == 0 ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Invalid pointer to CaloCellContainer (%p)",(void*)pCellCont) ); return false; + } else if ( pCellCont->empty() ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("CaloCellContainer at %p is empty (size %zu)",(void*)pCellCont,pCellCont->size()) ); return false; } -} + // check the atomic state + if ( CaloTopoClusterFromTowerMaker_checkCellIndices ) { return true; } + // set the atomic flag + ATH_MSG_INFO( "Cell hash index check requested" ); + CaloTopoClusterFromTowerMaker_checkCellIndices = true; + // assign output file + std::string algname(this->name()); + if ( algname.find_last_of('.') != std::string::npos ) { algname = algname.substr(algname.find_last_of('.')+1); } + std::string logname(CaloRec::Helpers::fmtMsg("%s.cellhash_index_check.dat",this->name().c_str())); + std::ofstream logstream; logstream.open(logname); + if ( !logstream.is_open() ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("Cannot open log file \042%s\042 - no hash index checking",logname.c_str()) ); + return false; + } + logstream << "##########################################################################" << std::endl; + logstream << "### This file contains a list of CaloCell indices in CaloCellContainer ###" << std::endl; + logstream << "### for which this index is not the same as the calorimeter cell hash ###" << std::endl; + logstream << "### identifier. An empty list indicates full consistency between this ###" << std::endl; + logstream << "### index and the hash identifier for all cells. ###" << std::endl; + logstream << "##########################################################################" << std::endl; + logstream << "<begin list>--------------------------------------------------------------" << std::endl; -bool CaloTopoClusterFromTowerMaker::buildInclClusters(const CaloCellContainer& pCellCont,protocont_t& pProtoCont) -{ - // inclusive mode - this->addMessage(CaloRec::Helpers::fmtMsg("Found %6i cell links in CaloCellTowerLink::Map::%s",(int)m_cellTowerLinksHandle->size(),m_cellTowerLinksKey.c_str())); + ///////////////////////// + // loop cell container // + ///////////////////////// - // loop cell container - size_t icl(0); - for ( auto cptr : pCellCont ) { - // FIXME check pointer value - if ( cptr == 0 ) { m_cellProblems.setInvalidPointer(icl,cptr); } - // existing cell - else { - if ( std::fabs(cptr->e()) > 0. ) { this->addCellToProtoCluster(cptr,pProtoCont); } + // prepare tag store + size_t ifc(0); std::bitset<200000> chkflg; chkflg.reset(); + for ( size_t i(0); i<pCellCont->size(); ++i ) { + if ( pCellCont->at(i) != 0 ) { + size_t chash((size_t)pCellCont->at(i)->caloDDE()->calo_hash()); + if ( chash != i ) { + std::string cni("UKNOWN"); + double etai(0.); double phii(0.); + const CaloDetDescrElement* iel = i < CaloDetDescrManager::instance()->element_size() ? CaloDetDescrManager::instance()->get_element(i) : 0; + if ( iel != 0 ) { + cni = CaloRec::Lookup::getSamplingName(iel->getSampling()); + etai = iel->eta_raw(); + phii = iel->phi_raw(); + } + std::string cnc("UNKNOWN"); + double etac(0.); double phic(0.); + const CaloDetDescrElement* cel = chash < CaloDetDescrManager::instance()->element_size() ? CaloDetDescrManager::instance()->get_element(chash) : 0; + if ( cel != 0 ) { + cnc = CaloRec::Lookup::getSamplingName(cel->getSampling()); + etac = cel->eta_raw(); + phic = cel->phi_raw(); + } + size_t cidx(pCellCont->findIndex(chash)); + logstream << CaloRec::Helpers::fmtMsg("[%06zu] Cell %6zu [%12.12s %5.3f %5.3f] non-matching id %6zu [%12.12s %5.3f %5.3f] findCell() index %6zu", + ++ifc,i,cni.c_str(),etai,phii,chash,cnc.c_str(),etac,phic,cidx) << std::endl; + } + chkflg.set(chash); } - ++icl; - } // cell loop - return true; -} - -bool CaloTopoClusterFromTowerMaker::buildExclClusters(const CaloCellContainer& pCellCont,protocont_t& pProtoCont) -{ - // inclusive mode - this->addMessage(CaloRec::Helpers::fmtMsg("Found %6i cell links in CaloCellTowerLink::Map::%s",(int)m_cellTowerLinksHandle->size(),m_cellTowerLinksKey.c_str())); + } + logstream << "<end list>----------------------------------------------------------------" << std::endl; + logstream.close(); - // loop cell container - for ( auto cptr : pCellCont ) { - // FIXME check pointer value - if ( cptr == 0 ) { m_cellProblems.setInvalidPointer(999999,cptr); } - // existing cell - else { - if ( cptr->e() > m_energyThreshold ) { this->addCellToProtoCluster(cptr,pProtoCont); } - } - } // cell loop - return true; -} + ///////////////////////// + // check missed hashes // + ///////////////////////// -// bool CaloTopoClusterFromTowerMaker::buildFilteredClusters(const CaloCellContainer& pCellCont,protocont_t& pProtoCont) -// { -// // inclusive mode -// this->addMessage(CaloRec::Helpers::fmtMsg("Found %6i cell links in CaloCellTowerLink::Map::%s",(int)m_cellTowerLinksHandle->size(),m_cellTowerLinksKey.c_str())); - -// // loop cell container -// size_t icl(0); -// for ( auto cptr : pCellCont ) { -// // FIXME check pointer value -// if ( cptr == 0 ) { m_cellProblems.setInvalidPointer(icl,cptr); } -// // existing cell -// else { -// size_t idx(static_cast<size_t>(cptr->caloDDE()->calo_hash_id())); -// if ( m_cellTagStore[idx].get<0>() ) { if ( std::fabs(cptr->e()) > 0. ) { this->addCellToProtoCluster(cptr,pProtoCont); } } -// } -// ++icl; -// } // cell loop -// return true; -// } - -bool CaloTopoClusterFromTowerMaker::addCellToProtoCluster(const CaloCell* cptr,protocont_t& pProtoCont) -{ - if ( cptr == 0 ) { return false; } - // cell hash - int cellidx(cptr->caloDDE()->calo_hash()); - if ( cellidx >= (int)m_cellTowerLinksHandle->size() ) { - this->addWarning(CaloRec::Helpers::fmtMsg("CaloCell [%06i] has hash outside of link lookup (max hash is %i)",cellidx,(int)m_cellTowerLinksHandle->size())); - return false; + // number of non-matched hashes + if ( ifc > 0 ) { + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("Found %zu non-matching cell hashes",ifc) ); + } + // list of non-matched hashes + std::vector<size_t> chl; chl.reserve(m_towerGeometrySvc->totalNumberCells()); + for ( size_t i(0); i<chl.size(); ++i ) { if ( !chkflg.test(i) ) { chl.push_back(i); } } + if ( !chl.empty() ) { + for ( auto h : chl ) { ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("Cell hash %6zu not in CaloCellContainer",h) ); } } - if ( cellidx < m_numberOfCells ) { - for ( auto link : m_cellTowerLinksHandle->elementList(cellidx) ) { - int towidx(CaloCellTowerLink::towerIndex(link)); - if ( towidx < (int)pProtoCont.size() ) { pProtoCont[towidx]->addCell(cellidx,CaloCellTowerLink::cellWeight(link)); } - else { this->addWarning(CaloRec::Helpers::fmtMsg("Invalid tower index %i (not in [0,%i])",(int)towidx,(int)pProtoCont.size()-1)); } - } // loop all cell->tower links - } // valid hash index + return true; } + diff --git a/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerMonitor.cxx b/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerMonitor.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ad12d4b149b8279ef12c6b55620e99888c6a3c4b --- /dev/null +++ b/Calorimeter/CaloRec/src/CaloTopoClusterFromTowerMonitor.cxx @@ -0,0 +1,421 @@ + +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/SystemOfUnits.h" +#include "GaudiKernel/PhysicalConstants.h" + +#include "CaloRec/CaloTopoClusterFromTowerMonitor.h" + +#include "CaloGeoHelpers/CaloPhiRange.h" + +#include "CaloDetDescr/CaloDetDescrElement.h" +#include "CaloDetDescr/CaloDetDescrManager.h" + +#include "TH1D.h" +#include "TH2D.h" + +#include <vector> + +namespace { + MsgStream& operator<<(MsgStream& mstr,const SG::ReadHandleKey<xAOD::CaloClusterContainer>& ckey) { mstr << ckey.key(); return mstr; } + MsgStream& operator<<(MsgStream& mstr,const ServiceHandle<CaloTowerGeometrySvc>& shdl) { mstr << shdl->name(); return mstr; } +} + +CaloTopoClusterFromTowerMonitor::CaloTopoClusterFromTowerMonitor(const std::string& name,ISvcLocator* pSvcLocator) + : AthHistogramAlgorithm(name,pSvcLocator) + , m_towerContainerKey("LCWTowerTopoClusterStd") + , m_towerGeometrySvc("CaloTowerGeometrySvc",name) + , m_ncBins(100) + , m_ncMin(-0.5) + , m_ncMax(m_ncMin+m_ncBins) + , m_nBins(320) + , m_nMin(-0.05) + , m_nMax(m_nMin+m_nBins*20.) + , m_ptBins(220) + , m_ptMin(-10.) + , m_ptMax(100.) + , m_etaBins(100) + , m_etaMin(-5.) + , m_etaMax(5.) + , m_phiBins(64) + , m_phiMin(-Gaudi::Units::pi) + , m_phiMax(Gaudi::Units::pi) + , m_hsEtaMin(0.) + , m_hsEtaMax(0.1) + , m_hsPhiMin(0.) + , m_hsPhiMax(0.1) + , m_doGeoAutoBins(true) + , m_doHotspot(false) + , h_n((TH1D*)0), h_pt((TH1D*)0), h_eta((TH1D*)0), h_phi((TH1D*)0), h_nc((TH1D*)0), h_samp((TH1D*)0) + , d_n_eta_phi((TH2D*)0), d_nc_eta_phi((TH2D*)0) + , d_pt_eta((TH2D*)0), d_nc_eta((TH2D*)0) + , d_wgt_samp((TH2D*)0), d_ntt_samp((TH2D*)0), d_geo_samp((TH2D*)0) + , d_maxtowers_samp((TH2D*)0), d_wgttowers_samp((TH2D*)0) + , d_maxcells_eta((TH2D*)0), d_allwghts_eta((TH2D*)0) + , d_deta_eta((TH2D*)0), d_dphi_eta((TH2D*)0), d_dphi_deta((TH2D*)0) + , d_detac_eta((TH2D*)0), d_dphic_eta((TH2D*)0), d_dphic_detac((TH2D*)0), d_detac_samp((TH2D*)0), d_dphic_samp((TH2D*)0) + , h_nc_hs((TH1D*)0), h_n_hs((TH1D*)0), h_pt_hs((TH1D*)0), h_eta_hs((TH1D*)0), h_phi_hs((TH1D*)0), h_samp_hs((TH1D*)0) + , d_n_eta_phi_hs((TH2D*)0), d_nc_eta_phi_hs((TH2D*)0) + , d_deta_eta_hs((TH2D*)0), d_dphi_eta_hs((TH2D*)0), d_dphi_deta_hs((TH2D*)0) + , d_detac_eta_hs((TH2D*)0), d_dphic_eta_hs((TH2D*)0), d_dphic_detac_hs((TH2D*)0), d_detac_samp_hs((TH2D*)0), d_dphic_samp_hs((TH2D*)0) +{ + declareProperty("CaloTowerContainerKey", m_towerContainerKey, "Input container key" ); + declareProperty("CaloTowerGeometrySvc", m_towerGeometrySvc, "Tower geometry provider" ); + declareProperty("NTowerCellsBins", m_ncBins, "Number of bins in cell-in-tower multiplicity"); + declareProperty("NTowerCellsMin", m_ncMin, "Lower limit in cell-in-tower multiplicity"); + declareProperty("NTowerCellsMax", m_ncMax, "Upper limit in cell-in-tower multiplicity"); + declareProperty("NTowersBins", m_nBins, "Number of bins in tower multiplicity binning"); + declareProperty("NTowersMin", m_nMin, "Lower limit in tower multiplicity binning"); + declareProperty("NTowersMax", m_nMax, "Upper limit in tower multiplicity binning"); + declareProperty("PtTowersBins", m_ptBins, "Number of bins in tower pT binning"); + declareProperty("PtTowersMin", m_ptMin, "Lower limit in tower pT binning"); + declareProperty("PtTowersMax", m_ptMax, "Upper limit in tower pT binning"); + declareProperty("EtaTowersBins", m_etaBins, "Number of bins in tower rapidity binning"); + declareProperty("EtaTowersMin", m_etaMin, "Lower limit in tower rapidity binning"); + declareProperty("EtaTowersMax", m_etaMax, "Upper limit in tower rapidity binning"); + declareProperty("PhiTowersBins", m_phiBins, "Number of bins in tower azimuth binning"); + declareProperty("PhiTowersMin", m_phiMin, "Lower limit in tower azimuth binning"); + declareProperty("PhiTowersMax", m_phiMax, "Upper limit in tower azimuth binning"); + declareProperty("EtaMinHotspot", m_hsEtaMin, "lower limit in tower rapidity for hotspot"); + declareProperty("EtaMaxHotspot", m_hsEtaMax, "Upper limit in tower rapidity for hotspot"); + declareProperty("PhiMinHotspot", m_hsPhiMin, "lower limit in tower azimuth for hotspot"); + declareProperty("PhiMaxHotspot", m_hsPhiMax, "Upper limit in tower azimuth for hotspot"); + declareProperty("DoGeoAutoBins", m_doGeoAutoBins, "Flag controls automatic binning for rapidity and azimuth"); +} + +CaloTopoClusterFromTowerMonitor::~CaloTopoClusterFromTowerMonitor() +{ } + +StatusCode CaloTopoClusterFromTowerMonitor::initialize() +{ + // initialize read handle key + ATH_CHECK(m_towerContainerKey.initialize()); + + // tower geometry service + ATH_MSG_INFO( "Allocate tower geometry service:" ); + if ( !m_towerGeometrySvc.isValid() ) { + ATH_MSG_ERROR("[reject] - cannot allocate tower geometry service - fatal"); + return StatusCode::FAILURE; + } else { + ATH_MSG_INFO( "[accept] - allocated tower geometry provider \042" << m_towerGeometrySvc << "\042"); + } + + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("Tower geometry service is allocated, describes %6zu towers in grid:", m_towerGeometrySvc->towerBins()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("[accept] %3zu eta bins in [%5.2f,%5.2f]",m_towerGeometrySvc->etaBins(),m_towerGeometrySvc->etaMin(),m_towerGeometrySvc->etaMax()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("[accept] %3zu phi bins in [%5.2f,%5.2f]",m_towerGeometrySvc->phiBins(),m_towerGeometrySvc->phiMin(),m_towerGeometrySvc->phiMax()) ); + + std::string cfgStr; + if ( m_doGeoAutoBins ) { + ATH_MSG_INFO("Eta and phi binning taken from tower geometry provider"); + m_etaBins = m_towerGeometrySvc->etaBins(); + m_etaMin = m_towerGeometrySvc->etaMin(); + m_etaMax = m_towerGeometrySvc->etaMax(); + m_phiBins = m_towerGeometrySvc->phiBins(); + m_phiMin = m_towerGeometrySvc->phiMin(); + m_phiMax = m_towerGeometrySvc->phiMax(); + m_hsPhiMax = m_hsPhiMin+m_towerGeometrySvc->phiWidth(); + cfgStr = "autoconfig"; + } else { + ATH_MSG_INFO("Eta and phi binning taken from specific configuration"); + cfgStr = "userconfig"; + } + + m_doHotspot = m_hsEtaMin < m_hsEtaMax && m_hsPhiMin < m_hsPhiMax; + + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("Eta and phi binning for histograms (total %zu towers)",m_etaBins*m_phiBins) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("[%s] %3zu eta bins in [%5.2f,%5.2f]",cfgStr.c_str(),m_etaBins,m_etaMin,m_etaMax) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("[%s] %3zu phi bins in [%5.2f,%5.2f]",cfgStr.c_str(),m_phiBins,m_phiMin,m_phiMax) ); + + ATH_CHECK( book() ); + + // database plots + std::vector<std::vector<double> > cWghts(m_towerGeometrySvc->towerBins(),std::vector<double>()); + size_t chash(0); + for ( auto fLnk(m_towerGeometrySvc->begin()); fLnk != m_towerGeometrySvc->end(); ++fLnk, ++chash ) { + CaloSampling::CaloSample samp = CaloDetDescrManager::instance()->get_element(chash)->getSampling(); + double cs(static_cast<double>(samp)); + double nt(static_cast<double>(fLnk->size())); + d_maxtowers_samp->Fill(cs,nt); + for ( auto elm : *fLnk ) { + // collect for towers + size_t tidx(static_cast<size_t>(m_towerGeometrySvc->towerIndex(elm))); + double weight(m_towerGeometrySvc->cellWeight(elm)); + cWghts[tidx].push_back(weight); + // plot for smaplings + d_wgttowers_samp->Fill(cs,weight); + } + } + + for ( size_t tidx(0); tidx<cWghts.size(); ++tidx ) { + double eta(m_towerGeometrySvc->towerEta(tidx)); + double phi(m_towerGeometrySvc->towerPhi(tidx)); + double nc(1.0*cWghts.at(tidx).size()); + d_maxcells_eta->Fill(eta,nc); + size_t etaIdx(m_towerGeometrySvc->etaIndexFromTowerIndex(tidx)); + d_maxcells_phi_eta_slice[etaIdx]->Fill(phi,nc); + for ( auto w : cWghts.at(tidx) ) { d_allwghts_eta->Fill(eta,w); d_allwghts_phi_eta_slice[etaIdx]->Fill(phi,w); } + } + + if ( msgLvl(MSG::DEBUG) ) { + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("+------------+--------------+") ); + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("| SamplingId | SamplingName |") ); + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("+------------+--------------+") ); + const auto& smap = CaloRec::Lookup::samplingNames; + for ( auto fsamp(smap.begin()); fsamp != smap.end(); ++fsamp ) { + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("| %02i | %11.11s |",fsamp->first,fsamp->second.c_str()) ); + } + ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("+------------+--------------+") ); + } + + return StatusCode::SUCCESS; +} + +StatusCode CaloTopoClusterFromTowerMonitor::book() +{ + //////////////////////////////////////////////////////////// + // composition, multiplicity, kinematics (event by event) // + //////////////////////////////////////////////////////////// + + int detaBins(105); int dphiBins(128); + double detaMin(-1.05); double dphiMin(-Gaudi::Units::pi/2.); + double detaMax(1.05); double dphiMax(Gaudi::Units::pi/2.); + + // re-center delta phi + double dphi((dphiMax-dphiMin)/(1.*dphiBins)); double dphiMinOld(dphiMin); double dphiMaxOld(dphiMax); //int dphiBinsOld(dphiBins); + int dphiBinsOld = (dphiMax-dphiMin)/dphi; + dphiMin -= (dphi/2.); dphiMax += (dphi/2.); + double dphim(dphi); + dphiBins = (dphiMax-dphiMin)/dphim; + + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("re-center delta_phi distributions, old/new binning [%6.3f,%6.3f]/[%6.3f,%6.3f] with %3i/%3i bins %5.3f/%5.3f rad wide", + dphiMinOld,dphiMaxOld,dphiMin,dphiMax,dphiBinsOld,dphiBins,dphi,dphim) ); + + + h_n = bookAny<TH1D>("TowerMultiplicity", "N_{tower}", m_nBins, m_nMin, m_nMax); + h_pt = bookAny<TH1D>("TowerPt", "p_{T}^{tower} [GeV]",m_ptBins,m_ptMin,m_ptMax); + h_nc = bookAny<TH1D>("TowerCellMultiplicity","N_{cell}^{tower}", m_ncBins,m_ncMin,m_ncMax); + h_eta = bookForEta<TH1D>("TowerRapidity", "y_{tower}"); + h_phi = bookForPhi<TH1D>("TowerAzimuth", "#phi_{tower} [rad]"); + + h_samp = bookForSamplings<TH1D>("TowerCellSamplings","TowerCellSamplings"); setAxisTitle(h_samp,"N_{cells} in sampling","y"); + // relations (event by event) + d_n_eta_phi = bookAny<TH2D>("TowerMultiplicityVsEtaVsPhi", "N_{tower}(y_{tower},#phi_{tower})", "y_{tower}",m_etaBins,m_etaMin,m_etaMax,m_phiBins,m_phiMin,m_phiMax); + setAxisTitle(d_n_eta_phi,"#phi_{tower} [rad]","y"); setAxisTitle(d_n_eta_phi,"N_{tower}","z"); + d_nc_eta_phi = bookAny<TH2D>("TowerCellMultiplicityVsEtaBsPhi","N_{cell}^{tower}(y_{tower},#phi_{tower})","y_{tower}",m_etaBins,m_etaMin,m_etaMax,m_phiBins,m_phiMin,m_phiMax); + setAxisTitle(d_nc_eta_phi,"#phi_{tower} [rad]","y"); setAxisTitle(d_nc_eta_phi,"N_{cell}^{tower}","z"); + d_pt_eta = bookAny<TH2D>("TowerPtVsEta", "p_{T}^{tower}(y_{tower})", "y_{tower}",m_etaBins,m_etaMin,m_etaMax,m_ptBins, m_ptMin, m_ptMax ); + setAxisTitle(d_pt_eta,"p_{T}^{tower} [GeV]","y"); + d_nc_eta = bookAny<TH2D>("TowerCellMultiplicityVsEta", "N_{cell}^{tower}(y_{tower})", "y_{tower}",m_etaBins,m_etaMin,m_etaMax,m_ncBins, m_ncMin, m_ncMax ); + setAxisTitle(d_pt_eta,"N_{cell}^{tower} [GeV]","y"); + // distance to nominal + d_deta_eta = bookAny<TH2D>("TowerDeltaEtaVsEta", "(y_{tower}-y_{tower,0})(y_{tower})", "y_{tower}", m_etaBins,m_etaMin,m_etaMax,detaBins,detaMin,detaMax); + setAxisTitle(d_deta_eta,"#Deltay_{tower}","y"); + d_dphi_eta = bookAny<TH2D>("TowerDeltaPhiVsEta", "(#phi_{tower}-#phi_{tower,0})(y_{tower})","y_{tower}", m_etaBins,m_etaMin,m_etaMax,dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphi_eta,"#Delta#phi_{tower} [rad]","y"); + d_dphi_deta = bookAny<TH2D>("TowerDeltaPhiVsDeltaEta", "#Delta#phi_{tower}(#Deltay_{tower})", "#Deltay_{tower}",detaBins, detaMin, detaMax, dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphi_deta,"#Delta#phi_{tower} [rad]","y"); + // cell distance to nominal + d_detac_eta = bookAny<TH2D>("CellDeltaEtaVsEta", "(y_{cell #in tower}#minusy_{tower,0})(y_{tower})", "y_{tower}", + m_etaBins,m_etaMin,m_etaMax,detaBins,detaMin,detaMax); + setAxisTitle(d_detac_eta,"#Deltay_{cell #in tower}","y"); + d_dphic_eta = bookAny<TH2D>("CellDeltaPhiVsEta", "(#phi_{cell #in tower}^{cell}#minus#phi_{tower,0})(y_{tower})","y_{tower}", + m_etaBins,m_etaMin,m_etaMax,dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphic_eta,"#Delta#phi_{cell #in tower}","y"); + d_dphic_detac = bookAny<TH2D>("CellDeltaPhiVsDeltaEta", "#Delta#phi_{cell #in tower}^{cell}(#Deltay_{tower}^{cell})", "#Deltay_{cell #in tower}", + detaBins,detaMin,detaMax,dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphic_detac,"#Delta#phi_{cell #in tower}","y"); + + /////////////////////////// + // features in samplings // + /////////////////////////// + + int fwbins(250); + double fwmin(-0.1); + double fwmax(4.9); + + int gwbins(60); + double gwmin(-0.1); + double gwmax(1.1); + + int ctbins(20); + double ctmin(-0.5); + double ctmax(19.5); + + // per event + d_wgt_samp = bookForSamplings<TH2D>("EvtFullWeightvsSampling", "[Event] Full weight vs sampling", fwbins,fwmin,fwmax); + setAxisTitle(d_wgt_samp,"w_{geo#plusLCW}","y"); + d_ntt_samp = bookForSamplings<TH2D>("EvtNTowersPerCellvsSampling","[Event] Number of towers/cell vs sampling", ctbins,ctmin,ctmax); + setAxisTitle(d_ntt_samp,"N_{towers}/cell","y"); + d_geo_samp = bookForSamplings<TH2D>("EvtGeoWeightvsSampling", "[Event] Geometrical weight vs sampling", gwbins,gwmin,gwmax); + setAxisTitle(d_geo_samp,"w_{geo}","y"); + d_detac_samp = bookForSamplings<TH2D>("EvtDetaCellvsSampling", "[Event] y_{cell #in tower}#minusy_{0}^{tower}", detaBins,detaMin,detaMax); + setAxisTitle(d_detac_samp,"#Deltay_{cell #in tower}","y"); + d_dphic_samp = bookForSamplings<TH2D>("EvtDphiCellvsSampling", "[Event] #phi_{cell #in tower}#minus#phi_{0}^{tower}",dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphic_samp,"#Delta#phi_{cell #in tower}","y"); + + // from database + d_maxtowers_samp = bookForSamplings<TH2D>("DBNTowersPerCellvsSampling", "[DB] Number of towers/cell vs sampling",ctbins,ctmin,ctmax); + setAxisTitle(d_maxtowers_samp,"N_{towers}/cell (maximum sharing)","y"); + d_wgttowers_samp = bookForSamplings<TH2D>("DBGeoWeightvsSampling", "[DB] Geometrical weight vs sampling", gwbins,gwmin,gwmax); + setAxisTitle(d_wgttowers_samp,"w_{geo} (from database)","y"); + + ///////////////////// + // features in eta // + ///////////////////// + + int tcbins(100); + double tcmin(-0.5); + double tcmax(99.5); + + d_maxcells_eta = bookForEta<TH2D>("DBNTowerCellsvsEta","[DB] Cells in towers vs y_{tower}", tcbins,tcmin,tcmax); setAxisTitle(d_maxcells_eta,"N_{cells #in tower} (from database)","y"); + d_allwghts_eta = bookForEta<TH2D>("DBGeoWeightvsEta", "[DB] Geometrical weight vs y_{tower}",gwbins,gwmin,gwmax); setAxisTitle(d_allwghts_eta,"w_{geo} (from database)","y"); + + // analyzing the database (in tower eta slices) + double deta((m_etaMax-m_etaMin)/(1.*m_etaBins)); + double eta0(m_etaMin); + + d_maxcells_phi_eta_slice.resize(m_etaBins,(TH2D*)0); + d_allwghts_phi_eta_slice.resize(m_etaBins,(TH2D*)0); + + std::string hname; std::string htitle; + for ( int i(0); i<m_etaBins; ++i, eta0+=deta ) { + hname = CaloRec::Helpers::fmtMsg("DBTowerCellsvsPhiEta%02i",i); + htitle = CaloRec::Helpers::fmtMsg("[DB] Cells in towers vs #phi_{tower} for y #in [%6.3f,%6.3f]",eta0,eta0+deta); + d_maxcells_phi_eta_slice[i] = bookForPhi<TH2D>(hname,htitle,tcbins,tcmin,tcmax); setAxisTitle(d_maxcells_phi_eta_slice.at(i),"N_{cells #in tower} (from database)","y"); + hname = CaloRec::Helpers::fmtMsg("DBGeoWeightvsPhiEta%02i",i); + htitle = CaloRec::Helpers::fmtMsg("[DB] Geometrical weight vs #phi_{tower} for y #in [%6.3f,%6.3f]",eta0,eta0+deta); + d_allwghts_phi_eta_slice[i] = bookForPhi<TH2D>(hname,htitle,gwbins,gwmin,gwmax); setAxisTitle(d_allwghts_phi_eta_slice.at(i),"w_{geo} (from database)","y"); + } + + ///////////////////////// + // debugging y=0,phi=0 // + ///////////////////////// + + if ( m_doHotspot ) { + h_n_hs = bookAny<TH1D>("HSTowerMultiplicity", "[Hotspot] N_{tower}", "N_{tower}", m_nBins, m_nMin, m_nMax); + h_pt_hs = bookAny<TH1D>("HSTowerPt", "[Hotspot] p_{T}^{tower}", "p_{T}^{tower} [GeV]",m_ptBins,m_ptMin,m_ptMax); + h_nc_hs = bookAny<TH1D>("HSTowerCellMultiplicity","[Hotspot] N_{cell}^{tower}","N_{cell}^{tower}", m_ncBins,m_ncMin,m_ncMax); + h_eta_hs = bookForEta<TH1D>("HSTowerEta", "[Hotspot] y_{tower}"); + h_phi_hs = bookForPhi<TH1D>("HSTowerPhi", "[Hotspot] #phi_{tower}"); + + h_samp_hs = bookForSamplings<TH1D>("HSTowerCellSampling","HSTowerCellSampling"); + + d_n_eta_phi_hs = bookAny<TH2D>("HSTowerMultiplicityVsEtaVsPhi", "[Hotspot] N_{tower}(y_{tower},#phi_{tower})" "y_{tower}",m_etaBins,m_etaMin,m_etaMax,m_phiBins,m_phiMin,m_phiMax); + setAxisTitle(d_n_eta_phi_hs,"#phi_{tower} [rad]","y"); setAxisTitle(d_n_eta_phi_hs,"N_{tower}","z"); + d_nc_eta_phi_hs = bookAny<TH2D>("HSTowerCellMultiplicityVsEtaVsPhi","[Hotspot] N_{cell}^{tower}(y_{tower},#phi_{tower})","y_{tower}",m_etaBins,m_etaMin,m_etaMax,m_phiBins,m_phiMin,m_phiMax); + setAxisTitle(d_nc_eta_phi_hs,"#phi_{tower} [rad]","y"); setAxisTitle(d_nc_eta_phi_hs,"N_{cell}^{tower}","z"); + d_deta_eta_hs = bookForEta<TH2D>("HSTowerDeltaEtaVsEta", "[Hotspot] #Deltay(y_{tower})",detaBins,detaMin,detaMax); setAxisTitle(d_deta_eta_hs,"#Deltay_{tower}","y"); + setAxisTitle(d_deta_eta_hs,"#Deltay_{tower}","y"); + d_dphi_eta_hs = bookForEta<TH2D>("HSTowerDeltaPhiVsEta", "[Hotspot] #Delta#phi(y_{tower})",dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphi_eta_hs,"#Delta#phi_{tower} [rad]","y"); + d_dphi_deta_hs = bookAny<TH2D>("HSTowerDeltaPhiVsDeltaEta", "[Hotspot] #Delta#phi_{tower}(#Deltay_{tower})","#Deltay_{tower}",detaBins,detaMin,detaMax,dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphi_deta_hs,"#Delta#phi_{tower} [rad]","y"); + d_detac_eta_hs = bookForEta<TH2D>("HSCellDeltaEtaVsEta", "[Hotspot] #Deltay_{cell #in tower}(y_{tower})",detaBins,detaMin,detaMax); + setAxisTitle(d_detac_eta_hs,"#Deltay_{cell #in tower}","y"); + d_dphic_eta_hs = bookForEta<TH2D>("HSCellDeltaPhiVsEta", "[Hotspot] #Delta#phi_{cell #in tower}(y_{tower})",dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphic_eta_hs,"#Delta#phi_{cell #in tower}","y"); + d_dphic_detac_hs = bookAny<TH2D>("HSCellDeltaPhiVsCellDeltaEta", "[Hotspot] #Delta#phi_{cell #in tower}(#Deltay_{cell #in tower})","#Deltay_{cell #in tower}", + detaBins,detaMin,detaMax,dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphic_detac_hs,"#Delta#phi_{cell #in tower}","y"); + d_detac_samp_hs = bookForSamplings<TH2D>("HSCellDeltaEtavsSampling", "[Hotspot] #Deltay_{cell #in tower} in samplings", detaBins,detaMin,detaMax); + setAxisTitle(d_detac_samp_hs,"#Deltay_{cell #in tower}","y"); + d_dphic_samp_hs = bookForSamplings<TH2D>("HSCelLDeltaPhivsSampling", "[Hotspot] #Delta#phi_{cell #in tower} in samplings",dphiBins,dphiMin,dphiMax); + setAxisTitle(d_dphic_samp_hs,"#Delta#phi_{cell #in tower}","y"); + } + + return StatusCode::SUCCESS; +} + +StatusCode CaloTopoClusterFromTowerMonitor::execute() +{ + SG::ReadHandle<xAOD::CaloClusterContainer> towerHandle(m_towerContainerKey); + if ( !towerHandle.isValid() ) { + ATH_MSG_ERROR( "cannot allocate cluster container with key <" << m_towerContainerKey << ">" ); + return StatusCode::FAILURE; + } + + // fill plots + size_t nhs(0); + m_cellTags.reset(); + std::vector<double> deta; deta.reserve(1000); + std::vector<double> dphi; dphi.reserve(deta.capacity()); + std::vector<CaloSampling::CaloSample> csam; csam.reserve(deta.capacity()); + h_n->Fill(1.0*towerHandle->size()); + for ( auto ftow(towerHandle->begin()); ftow!=towerHandle->end(); ++ftow ) { + const xAOD::CaloCluster* ptow = *ftow; + // tower kinematics + double pt(ptow->pt()/Gaudi::Units::GeV); + double eta(ptow->eta()); + double phi(CaloPhiRange::fix(ptow->phi())); + double nc(1.0*ptow->size()); + // tower composition and get distances + this->fillComposition(*ptow,deta,dphi,csam); + double deltaEta(ptow->eta()-ptow->eta0()); + double deltaPhi(CaloPhiRange::fix(ptow->phi()-ptow->phi0())); + // inclusive plots + h_pt->Fill(pt); h_eta->Fill(eta); h_phi->Fill(phi); h_nc->Fill(nc); + d_n_eta_phi->Fill(eta,phi); d_nc_eta_phi->Fill(eta,phi,nc); + d_pt_eta->Fill(eta,pt); + d_nc_eta->Fill(eta,nc); + d_deta_eta->Fill(eta,deltaEta); + d_dphi_eta->Fill(eta,deltaPhi); + d_dphi_deta->Fill(deltaEta,deltaPhi); + for ( size_t ic(0); ic<deta.size(); ++ic ) { + d_detac_eta->Fill(eta,deta.at(ic)); + d_dphic_eta->Fill(eta,dphi.at(ic)); + d_dphic_detac->Fill(deta.at(ic),dphi.at(ic)); + fillSampling<TH2D>(d_detac_samp,csam.at(ic),deta.at(ic)); + fillSampling<TH2D>(d_dphic_samp,csam.at(ic),dphi.at(ic)); + fillSampling<TH1D>(h_samp,csam.at(ic)); + } + // hot spot + if ( this->isInHotspot(*ptow) ) { + ++nhs; + h_pt_hs->Fill(pt); + h_eta_hs->Fill(eta); + h_phi_hs->Fill(phi); + h_nc_hs->Fill(nc); + d_n_eta_phi_hs->Fill(eta,phi); + d_nc_eta_phi_hs->Fill(eta,phi,nc); + d_deta_eta_hs->Fill(eta,deltaEta); + d_dphi_eta_hs->Fill(eta,deltaPhi); + d_dphi_deta_hs->Fill(deltaEta,deltaPhi); + for ( size_t ic(0); ic<deta.size(); ++ic ) { + d_detac_eta_hs->Fill(eta,deta.at(ic)); + d_dphic_eta_hs->Fill(eta,dphi.at(ic)); + d_dphic_detac_hs->Fill(deta.at(ic),dphi.at(ic)); + fillSampling<TH2D>(d_detac_samp_hs,csam.at(ic),deta.at(ic)); + fillSampling<TH2D>(d_dphic_samp_hs,csam.at(ic),dphi.at(ic)); + fillSampling<TH1D>(h_samp_hs,csam.at(ic)); + } + } + // fill in samplings + for ( auto fCell(ptow->getCellLinks()->begin()); fCell!=ptow->getCellLinks()->end(); ++fCell ) { + CaloSampling::CaloSample csamp = (*fCell)->caloDDE()->getSampling(); + fillSampling<TH2D>(d_wgt_samp,csamp,fCell.weight()); + // check for cell which other tower it contributes to and plot geometrical weights (only 1/cell) + size_t chash(static_cast<size_t>((*fCell)->caloDDE()->calo_hash())); + if ( !m_cellTags.test(chash) ) { + CaloTowerGeometrySvc::elementvector_t lOfTowers = m_towerGeometrySvc->getTowers(chash); + double ntowers(1.0*lOfTowers.size()); + fillSampling<TH2D>(d_ntt_samp,csamp,ntowers); + for ( auto elm : lOfTowers ) { fillSampling<TH2D>(d_geo_samp,csamp,m_towerGeometrySvc->cellWeight(elm)); } + m_cellTags.set(chash); + } + } + } + // number of towers in hot spot + h_n_hs->Fill(1.0*nhs); + + return StatusCode::SUCCESS; +} + +bool CaloTopoClusterFromTowerMonitor::fillComposition(const xAOD::CaloCluster& ptow,std::vector<double>& deta,std::vector<double>& dphi,std::vector<CaloSampling::CaloSample>& csam) const +{ + deta.clear(); dphi.clear(); csam.clear(); + for ( auto fCell(ptow.getCellLinks()->begin()); fCell != ptow.getCellLinks()->end(); ++fCell ) { + deta.push_back((*fCell)->eta()-ptow.eta0()); + dphi.push_back(CaloPhiRange::fix((*fCell)->phi()-ptow.phi0())); + csam.push_back((*fCell)->caloDDE()->getSampling()); + } + return !deta.empty(); +} diff --git a/Calorimeter/CaloRec/src/CaloTopoClusterTowerMerger.cxx b/Calorimeter/CaloRec/src/CaloTopoClusterTowerMerger.cxx new file mode 100644 index 0000000000000000000000000000000000000000..19e7b6085afa6613fa2c444f19d95b6c718beba4 --- /dev/null +++ b/Calorimeter/CaloRec/src/CaloTopoClusterTowerMerger.cxx @@ -0,0 +1,214 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "StoreGate/ReadHandle.h" +#include "StoreGate/WriteHandle.h" + +#include "xAODCaloEvent/CaloClusterAuxContainer.h" + +#include "CaloRec/CaloTopoClusterTowerMerger.h" +#include "CaloRec/CaloTopoClusterFromTowerHelpers.h" + +#include "CaloUtils/CaloClusterStoreHelper.h" + +// #include <atomic> + +// std::atomic<bool> CaloTopoClusterTowerMerger_checkMoments(true); + +// #define CL_MNAME( NAME ) xAOD::CaloCluster::NAME +// #define CL_ENTRY( NAME ) std::tuple< CL_MNAME( MomentType ),std::string>( CL_MNAME( NAME ), #NAME ) + +#define CL_RHMSG( NAME ) MsgStream& operator<<(MsgStream& mstr,const SG::ReadHandleKey< NAME >& ckey ) { mstr << ckey.key(); return mstr; } +#define CL_WHMSG( NAME ) MsgStream& operator<<(MsgStream& mstr,const SG::WriteHandleKey< NAME >& ckey ) { mstr << ckey.key(); return mstr; } + +namespace { + CL_RHMSG( xAOD::CaloClusterContainer ) +} + +// std::vector<xAOD::CaloCluster::MomentType> CaloTopoClusterTowerMerger::m_momentList = std::vector< CL_MNAME( MomentType ) >(); +// std::vector<std::tuple<xAOD::CaloCluster::MomentType,std::string> > CaloTopoClusterTowerMerger::m_momentMap { +// CL_ENTRY( FIRST_PHI ), +// CL_ENTRY( FIRST_ETA ), +// CL_ENTRY( SECOND_R ), +// CL_ENTRY( SECOND_LAMBDA ), +// CL_ENTRY( DELTA_PHI ), +// CL_ENTRY( DELTA_THETA ), +// CL_ENTRY( DELTA_ALPHA ), +// CL_ENTRY( CENTER_X ), +// CL_ENTRY( CENTER_Y ), +// CL_ENTRY( CENTER_Z ), +// CL_ENTRY( CENTER_MAG ), +// CL_ENTRY( CENTER_LAMBDA ), +// CL_ENTRY( LATERAL ), +// CL_ENTRY( LONGITUDINAL ), +// CL_ENTRY( ENG_FRAC_EM ), +// CL_ENTRY( ENG_FRAC_MAX ), +// CL_ENTRY( ENG_FRAC_CORE ), +// CL_ENTRY( FIRST_ENG_DENS ), +// CL_ENTRY( SECOND_ENG_DENS ), +// CL_ENTRY( ISOLATION ), +// CL_ENTRY( ENG_BAD_CELLS ), +// CL_ENTRY( N_BAD_CELLS ), +// CL_ENTRY( N_BAD_CELLS_CORR ), +// CL_ENTRY( BAD_CELLS_CORR_E ), +// CL_ENTRY( BADLARQ_FRAC ), +// CL_ENTRY( ENG_POS ), +// CL_ENTRY( SIGNIFICANCE ), +// CL_ENTRY( CELL_SIGNIFICANCE ), +// CL_ENTRY( CELL_SIG_SAMPLING ), +// CL_ENTRY( AVG_LAR_Q ), +// CL_ENTRY( AVG_TILE_Q ), +// CL_ENTRY( ENG_BAD_HV_CELLS ), +// CL_ENTRY( N_BAD_HV_CELLS ), +// CL_ENTRY( PTD ), +// CL_ENTRY( EM_PROBABILITY ), +// CL_ENTRY( HAD_WEIGHT ), +// CL_ENTRY( OOC_WEIGHT ), +// CL_ENTRY( DM_WEIGHT ), +// CL_ENTRY( TILE_CONFIDENCE_LEVEL ), +// CL_ENTRY( VERTEX_FRACTION ), +// CL_ENTRY( NVERTEX_FRACTION ), +// CL_ENTRY( ETACALOFRAME ), +// CL_ENTRY( PHICALOFRAME ), +// CL_ENTRY( ETA1CALOFRAME ), +// CL_ENTRY( PHI1CALOFRAME ), +// CL_ENTRY( ETA2CALOFRAME ), +// CL_ENTRY( PHI2CALOFRAME ), +// CL_ENTRY( ENG_CALIB_TOT ), +// CL_ENTRY( ENG_CALIB_OUT_L ), +// CL_ENTRY( ENG_CALIB_OUT_M ), +// CL_ENTRY( ENG_CALIB_OUT_T ), +// CL_ENTRY( ENG_CALIB_DEAD_L ), +// CL_ENTRY( ENG_CALIB_DEAD_M ), +// CL_ENTRY( ENG_CALIB_DEAD_T ), +// CL_ENTRY( ENG_CALIB_EMB0 ), +// CL_ENTRY( ENG_CALIB_EME0 ), +// CL_ENTRY( ENG_CALIB_TILEG3 ), +// CL_ENTRY( ENG_CALIB_DEAD_TOT ), +// CL_ENTRY( ENG_CALIB_DEAD_EMB0 ), +// CL_ENTRY( ENG_CALIB_DEAD_TILE0 ), +// CL_ENTRY( ENG_CALIB_DEAD_TILEG3 ), +// CL_ENTRY( ENG_CALIB_DEAD_EME0 ), +// CL_ENTRY( ENG_CALIB_DEAD_HEC0 ), +// CL_ENTRY( ENG_CALIB_DEAD_FCAL ), +// // CL_ENTRY( ENG_CALIB_DEAD_LEAKAG ), // not in r21 +// // CL_ENTRY( ENG_CALIB_DEAD_UNCLAS ), // not in r21 +// CL_ENTRY( ENG_CALIB_FRAC_EM ), +// CL_ENTRY( ENG_CALIB_FRAC_HAD ), +// CL_ENTRY( ENG_CALIB_FRAC_REST ) +// }; + +CaloTopoClusterTowerMerger::CaloTopoClusterTowerMerger(const std::string& name,ISvcLocator* pSvcLocator) + : AthAlgorithm(name,pSvcLocator) + , m_clusterContainerKey("CaloCalTopoCluster") + , m_towerContainerKey("CaloCalFwdTopoTower") + , m_topoSignalContainerKey("CaloCalTopoSignal") + // ** not in r21 **, m_cellLinkContainerKey("") + , m_clusterRange(3.2) +{ + declareProperty("TopoClusterContainerKey",m_clusterContainerKey, "Topo-cluster container key" ); + declareProperty("TopoTowerContainerKey", m_towerContainerKey, "Topo-tower container key" ); + declareProperty("TopoSignalContainerKey", m_topoSignalContainerKey,"Topo-signal container key" ); + declareProperty("TopoClusterRange", m_clusterRange, "Rapidity range for using topo-clusters in combined signal mode"); +} + +CaloTopoClusterTowerMerger::~CaloTopoClusterTowerMerger() +{ } + +StatusCode CaloTopoClusterTowerMerger::initialize() +{ + if ( m_clusterRange <= 0. ) { + ATH_MSG_ERROR( CaloRec::Helpers::fmtMsg("Invalid topo-cluster range |y| < %6.3f - algorithm non-functional",m_clusterRange) ); + return StatusCode::FAILURE; + } + + // ** not in r21 ** if ( m_cellLinkContainerKey.key().empty() ) { m_cellLinkKey = m_topoSignalContainerKey.key() + std::string("_links"); } + + ATH_CHECK( m_clusterContainerKey.initialize() ); + ATH_CHECK( m_towerContainerKey.initialize() ); + ATH_CHECK( m_topoSignalContainerKey.initialize() ); + // ** not in r21 ** ATH_CHECK( m_cellLinkContainerKey.initialize() ); + + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("Topo_cluster with |y| < %.2f will be merged with topo-towers with |y| > %.2f",m_clusterRange,m_clusterRange) ); + // if ( m_copyMoments ) { ATH_MSG_INFO( "Cluster moments are explicitly copied." ); } + + return StatusCode::SUCCESS; +} + +StatusCode CaloTopoClusterTowerMerger::execute() +{ + + // collect input + rhandle_t clusterHandle(m_clusterContainerKey); + if ( !clusterHandle.isValid() ) { + ATH_MSG_WARNING( "Topo-cluster container with key <" << m_clusterContainerKey << "> not found" ); + return StatusCode::SUCCESS; + } + rhandle_t towerHandle(m_towerContainerKey); + if ( !towerHandle.isValid() ) { + ATH_MSG_WARNING( "Topo-tower container with key <" << m_towerContainerKey << "> not found" ); + return StatusCode::SUCCESS; + } + + // prepare output + whandle_t signalHandle(m_topoSignalContainerKey); + ATH_CHECK(this->addContainerWriteHandle(signalHandle)); + + // check cluster moments + // if ( m_copyMoments ) { if ( CaloTopoClusterTowerMerger_checkMoments ) { this->fillMoments(*(towerHandle.ptr()->front())); CaloTopoClusterTowerMerger_checkMoments = false; } } + + // fill output from topo-clusters + for ( auto pClus : *clusterHandle ) { if ( clusterFilter(*pClus) ) { this->makeDeepCopy(*pClus,signalHandle.ptr()); } } + // fill output from topo-towers + for ( auto pTowr : *towerHandle ) { if ( towerFilter(*pTowr) ) { this->makeDeepCopy(*pTowr,signalHandle.ptr()); } } + + // take care of cell links + ATH_CHECK(CaloClusterStoreHelper::finalizeClusters(&(*evtStore()),signalHandle.ptr(),m_topoSignalContainerKey.key(),msg())); + + return StatusCode::SUCCESS; +} + +// bool CaloTopoClusterTowerMerger::fillMoments(const xAOD::CaloCluster& rClus) +// { +// m_momentList.reserve(m_momentMap.size()); +// double val(0); +// if ( !msgLvl(MSG::DEBUG) ) { +// for ( auto fmom(m_momentMap.begin()); fmom != m_momentMap.end(); ++fmom ) { +// if ( rClus.retrieveMoment(std::get<0>(*fmom),val) ) { m_momentList.push_back(std::get<0>(*fmom)); } +// } +// } else { +// ATH_MSG_DEBUG("###############################"); +// ATH_MSG_DEBUG("## Moments (topo-towers) ##"); +// ATH_MSG_DEBUG("##---------------------------##"); +// for ( auto fmom(m_momentMap.begin()); fmom != m_momentMap.end(); ++fmom ) { +// if ( rClus.retrieveMoment( std::get<0>(*fmom), val ) ) { +// m_momentList.push_back(std::get<0>(*fmom)); +// ATH_MSG_DEBUG( CaloRec::Helpers::fmtMsg("## %5.5x | \042%16.16s\042 ##", std::get<0>(*fmom), std::get<1>(*fmom).c_str()) ); +// } +// } +// ATH_MSG_DEBUG("###############################"); +// } // debug mode +// return true; +// } + +bool CaloTopoClusterTowerMerger::makeDeepCopy(const xAOD::CaloCluster& rClus,xAOD::CaloClusterContainer* pClusCont) const +{ pClusCont->push_back(new xAOD::CaloCluster(rClus)); return true; } + +StatusCode CaloTopoClusterTowerMerger::addContainerWriteHandle(whandle_t& signalHandle) +{ + // get a new signal handle + signalHandle = std::unique_ptr<xAOD::CaloClusterContainer>(new xAOD::CaloClusterContainer()); + if ( !signalHandle.isValid() ) { return StatusCode::FAILURE; } + // get AUX container + xAOD::CaloClusterAuxContainer* auxData = new xAOD::CaloClusterAuxContainer(); + std::string auxName(m_topoSignalContainerKey.key()+"Aux."); + if ( evtStore()->overwrite(auxData,auxName).isFailure() ) { + ATH_MSG_ERROR("Failed to record xAOD::CaloClusterAuxContainer with key <" << auxName << ">"); + delete auxData; + return StatusCode::FAILURE; + } + // connect store with object container + signalHandle.ptr()->setStore(auxData); + return StatusCode::SUCCESS; +} diff --git a/Calorimeter/CaloRec/src/CaloTowerGeometrySvc.cxx b/Calorimeter/CaloRec/src/CaloTowerGeometrySvc.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e1dfdcabc7b382581853a7a7dc9fd908d4864310 --- /dev/null +++ b/Calorimeter/CaloRec/src/CaloTowerGeometrySvc.cxx @@ -0,0 +1,410 @@ +/* Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ +#include "CaloRec/CaloTowerGeometrySvc.h" +#include "CaloRec/CaloTopoClusterFromTowerHelpers.h" + +#include <cmath> + +namespace { constexpr auto _pi = 3.14159265358979323846; } + +CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::m_invalidIndex = index_t(-1); +double CaloTowerGeometrySvc::m_invalidValue = -999.; + +CaloTowerGeometrySvc::CaloTowerGeometrySvc(const std::string& name,ISvcLocator* pSvcLocator) + : AthService(name,pSvcLocator) + , m_caloDDM((const CaloDetDescrManager*)0) + , m_logFileName("logfile") + , m_towerEtaWidth(0.) + , m_towerPhiWidth(0.) + , m_towerArea(0.) + , m_towerBins(0) + , m_maxCellHash(0) //----------------------------------------// + , m_towerEtaBins(100) // Default tower definition is "hadronic" // + , m_towerEtaMin(-5.0) // towers of size 0.1 x pi/32. // + , m_towerEtaMax(5.0) //----------------------------------------// + , m_adjustEta(true) + , m_towerPhiBins(64) + , m_towerPhiMin(-_pi) //----------------------------------------// + , m_towerPhiMax(_pi) // FCal vertical and horizontal cell // + , m_fcal1Xslice(8.) // slicing creates "mini-cells" which are // + , m_fcal1Yslice(8.) // then projected onto towers. The mini- // + , m_fcal2Xslice(8.) // cell signal is 1/(Nx x Ny) x Ecell, // + , m_fcal2Yslice(12.) // where Nx(y) are the number of x(y) // + , m_fcal3Xslice(12.) // slices. // + , m_fcal3Yslice(12.) //----------------------------------------// +{ + // Properties + declareProperty("TowerEtaBins", m_towerEtaBins, "Number of pseudorapidity bins in tower grid"); + declareProperty("TowerEtaMin", m_towerEtaMin, "Lower boundary of pseudorapidity range"); + declareProperty("TowerEtaMax", m_towerEtaMax, "Upper boundary of pseudorapidity range"); + declareProperty("AdjustFCalToTowerEtaBounds", m_adjustEta, "Adjust FCal cells to eta boundaries"); + declareProperty("TowerPhiBins", m_towerPhiBins, "Number of azimuthal bins in tower grid"); + declareProperty("TowerPhiMin", m_towerPhiMin, "Lower boundary of azimuthal range"); + declareProperty("TowerPhiMax", m_towerPhiMax, "Upper boundary of azimuthal range"); + // change only for R&D + declareProperty("FCal1NSlicesX", m_fcal1Xslice, "Number of X slices for FCal1 cells"); + declareProperty("FCal1NSlicesY", m_fcal1Yslice, "Number of Y slices for FCal1 cells"); + declareProperty("FCal2NSlicesX", m_fcal2Xslice, "Number of X slices for FCal2 cells"); + declareProperty("FCal2NSlicesY", m_fcal2Yslice, "Number of Y slices for FCal2 cells"); + declareProperty("FCal3NSlicesX", m_fcal3Xslice, "Number of X slices for FCal3 cells"); + declareProperty("FCal3NSlicesY", m_fcal3Yslice, "Number of Y slices for FCal3 cells"); +} + +//-------------// +// Gaudi stuff // +//-------------// + +StatusCode CaloTowerGeometrySvc::queryInterface(const InterfaceID& riid,void** ppvInterface) +{ + if ( CaloTowerGeometrySvc::interfaceID().versionMatch(riid) ) { + *ppvInterface = this; + return StatusCode::SUCCESS; + } else { + return AthService::queryInterface(riid,ppvInterface); + } +} + +//-------------------------// +// Initialize and Finalize // +//-------------------------// + +StatusCode CaloTowerGeometrySvc::initialize() +{ + // set up services and managers + if ( f_setupSvc().isFailure() ) { + ATH_MSG_ERROR("Cannot allocate the calorimeter detector description manager"); + return StatusCode::FAILURE; + } + + // prepare FCal segmentation + m_ndxFCal[0] = m_fcal1Xslice; m_ndxFCal[1] = m_fcal2Xslice; m_ndxFCal[2] = m_fcal3Xslice; + m_ndyFCal[0] = m_fcal1Yslice; m_ndyFCal[1] = m_fcal2Yslice; m_ndyFCal[2] = m_fcal3Yslice; + for ( uint_t i(0); i<m_ndxFCal.size(); ++i ) { m_wgtFCal[i] = 1./(m_ndxFCal.at(i)*m_ndyFCal.at(i)); } + + // other derived quantities + if ( m_towerEtaBins > 0 ) { + m_towerEtaWidth = (m_towerEtaMax-m_towerEtaMin)/((double)m_towerEtaBins); + } else { + ATH_MSG_ERROR("Number of tower eta bins is invalid (" << m_towerEtaBins << " bins)"); + return StatusCode::FAILURE; + } + if ( m_towerPhiBins > 0 ) { + m_towerPhiWidth = (m_towerPhiMax-m_towerPhiMin)/((double)m_towerPhiBins); + } else { + ATH_MSG_ERROR("Number of tower phi bins is invalid (" << m_towerPhiBins << " bins)"); + return StatusCode::FAILURE; + } + + m_towerBins = m_towerEtaBins*m_towerPhiBins; + m_towerArea = m_towerEtaWidth*m_towerPhiWidth; + m_maxCellHash = f_caloDDM()->element_size()-1; + m_numberOfCells = f_caloDDM()->element_size(); + + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("Tower description - Eta(bins,min,max,width) = (%3zu,%6.3f,%6.3f,%6.4f)",m_towerEtaBins,m_towerEtaMin,m_towerEtaMax,m_towerEtaWidth) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("Tower description - Phi(bins,min,max,width) = (%3zu,%6.3f,%6.3f,%6.4f)",m_towerPhiBins,m_towerPhiMin,m_towerPhiMax,m_towerPhiWidth) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("Tower description - maximum number of towers %5zu; (eta,phi)-space area %6.4f; maximum cell hash index %6zu",m_towerBins,m_towerArea,m_maxCellHash) ); + + if ( this->msgLvl(MSG::VERBOSE) ) { + std::vector<std::string> logger; logger.reserve(m_towerBins+10); + logger.push_back(CaloRec::Helpers::fmtMsg("[CaloTowerGeometrySvc::%s] +-------- Tower Index Mapping ---------+------------+------------+",this->name().c_str())); + logger.push_back(CaloRec::Helpers::fmtMsg("[CaloTowerGeometrySvc::%s] | %10.10s | %10.10s | %10.10s | %10.10s | %10.10s |",this->name().c_str(),"TowerIndex", " EtaIndex ", " PhiIndex "," Eta "," Phi ")); + logger.push_back(CaloRec::Helpers::fmtMsg("[CaloTowerGeometrySvc::%s] +------------+------------+------------+------------+------------+",this->name().c_str())); + for ( size_t i(0); i<m_towerBins; ++i ) { + size_t etaIndex(this->etaIndexFromTowerIndex(i)); + size_t phiIndex(this->phiIndexFromTowerIndex(i)); + double eta(this->towerEta(i)); double phi(this->towerPhi(i)); + logger.push_back(CaloRec::Helpers::fmtMsg("[CaloTowerGeometrySvc::%s] | %5zu | %5zu | %5zu | %6.3f | %6.3f |",this->name().c_str(),i,etaIndex,phiIndex,eta,phi)); + } + logger.push_back(CaloRec::Helpers::fmtMsg("[CaloTowerGeometrySvc::%s] +------------+------------+------------+------------+------------+",this->name().c_str())); + // + std::string logFileName = m_logFileName+"."+this->name()+".dat"; + std::ofstream logfile; + logfile.open(logFileName); for ( auto mlog : logger ) { logfile << mlog << std::endl; } logfile.close(); + } + return f_setupTowerGrid(); +} + +StatusCode CaloTowerGeometrySvc::finalize() +{ return StatusCode::SUCCESS; } + +//-------// +// Setup // +//-------// + +StatusCode CaloTowerGeometrySvc::f_setupTowerGrid() +{ + // initialized + if ( m_maxCellHash == 0 ) { + ATH_MSG_ERROR("Service not initialized? Maximum cell hash is " << m_maxCellHash ); + return StatusCode::FAILURE; + } + + // payload template + elementvector_t ev; + + // set up lookup table + ATH_MSG_INFO( "Setting up cell-to-tower lookup for " << m_numberOfCells << " calorimeter cells" ); + m_towerLookup.resize(m_numberOfCells,ev); + + // dump projections + std::ofstream logger; + if ( msgLvl(MSG::DEBUG) ) { + logger.open(CaloRec::Helpers::fmtMsg("%s.calocellprojections_dump.dat",this->name().c_str())); + logger << CaloRec::Helpers::fmtMsg("############################################################################") << std::endl; + logger << CaloRec::Helpers::fmtMsg("## CaloCell projections onto %3.1f x %3.1f tower grid (projective cells only) ##",m_towerEtaWidth,m_towerPhiWidth) << std::endl; + logger << CaloRec::Helpers::fmtMsg("############################################################################") << std::endl; + logger << std::endl; + } + + // loop cells + for ( auto fcell(m_caloDDM->element_begin()); fcell != m_caloDDM->element_end(); ++fcell ) { + // reference cell descriptor + const CaloDetDescrElement* pCaloDDE = *fcell; + // check hash id validity + index_t cidx(pCaloDDE->calo_hash()); + if ( cidx >= m_towerLookup.size() ) { + ATH_MSG_WARNING( "Cell hash identifier out of range " << cidx << "/" << m_towerLookup.size() << ", ignore cell" ); + } else { + if ( pCaloDDE->is_lar_fcal() ) { + if ( this->f_setupTowerGridFCal(pCaloDDE,logger).isFailure() ) { return StatusCode::FAILURE; } + } else { + if ( this->f_setupTowerGridProj(pCaloDDE,logger).isFailure() ) { return StatusCode::FAILURE; } + } + } // cell hash in range? + } // loop cell descriptors + if ( logger.is_open() ) { logger.close(); } + + return StatusCode::SUCCESS; +} + +StatusCode CaloTowerGeometrySvc::f_setupTowerGridFCal(const CaloDetDescrElement* pCaloDDE,std::ofstream& /*logger*/) +{ + //-----------------------------------------------------------------------------------------// + // FCal special - the rectangular (in linear space) calorimeter cells are sub-divided into // + // small cells and then shared across as many towers as the small cells cover. // + //-----------------------------------------------------------------------------------------// + + // collect geometrical variables + int cLayer(pCaloDDE->getLayer()-1); // FCal layer number 1..3 -> array indices 0..2 + + double cXpos(pCaloDDE->x()); // FCal cell x position (cell center) + double cYpos(pCaloDDE->y()); // FCal cell y position (cell center) + double cZpos(pCaloDDE->z()); // FCal cell z position (cell center) + double cZpos2(cZpos*cZpos); + + double cXwid(pCaloDDE->dx()); // FCal cell x full width + double cYwid(pCaloDDE->dy()); // FCal cell y full width + + // double xSlice(cXwid/m_ndxFCal[cLayer]); // FCal cell x slize width + // double ySlice(cYwid/m_ndyFCal[cLayer]); // FCal cell y slice width + double cWght(m_wgtFCal[cLayer]); // FCal cell geometrical (signal) weight + + int nXslice((int)m_ndxFCal[cLayer]); // FCal number of x slices + int nYslice((int)m_ndyFCal[cLayer]); // FCal number of y slices + double cXstp(cXwid/((double)nXslice)); // FCal slice x width + double cYstp(cYwid/((double)nYslice)); // FCal slice y width + + // fill cell fragments + // double xoff(cXpos-cXwid/2.+cXstp/2.); double yoff(cYpos-cYwid/2.+cYstp/2.); + double x(cXpos-(cXwid-cXstp)/2.); + double xlim(cXpos+cXwid/2.); double ylim(cYpos+cYwid/2.); + double etaOrig(0.); + // for ( int ix(0); ix < nXslice; ++ix ) { + // double x(xoff+ix*cXstp); + while ( x < xlim ) { + // for ( int iy(0); iy < nYslice; ++iy ) { + // double y(yoff+iy*cYstp); + double y(cYpos-(cYwid-cYstp)/2.); + while ( y < ylim ) { + double r(std::sqrt(x*x+y*y+cZpos2)); + double eta(-0.5*std::log((r-cZpos)/(r+cZpos))); + bool etaAdjusted(false); + if ( m_adjustEta ) { + if ( eta < m_towerEtaMin ) { + etaAdjusted = true; + etaOrig = eta; + eta = m_towerEtaMin+m_towerEtaWidth/2.; + } else if ( eta > m_towerEtaMax ) { + etaAdjusted = true; + etaOrig = eta; + eta = m_towerEtaMax-m_towerEtaWidth/2.; + } + } + double phi(CaloPhiRange::fix(std::atan2(y,x))); + index_t towerIdx(this->towerIndex(eta,phi)); + // tower index not valid + if ( isInvalidIndex(towerIdx) ) { + ATH_MSG_WARNING("Found invalid tower index for FCal cell (eta,phi) = (" << eta << "," << phi << ") at (x,y,z) = (" << x << "," << y << "," << cZpos << ") [cell ignored]"); + } else { + // add tower to lookup + if ( etaAdjusted ) { + ATH_MSG_WARNING("FCal cell direction (eta,phi) = (" << etaOrig << "," << phi << ") for cell at (x,y,z) = (" + << x << "," << y << "," << cZpos << ") adjusted to (eta,phi) = (" << eta << "," << phi << ") [cell adjusted]"); + } + f_assign(pCaloDDE->calo_hash(),towerIdx,cWght); + } // tower index ok + y += cYstp; + } // loop on y fragments + x += cXstp; + } // loop on x fragments + return StatusCode::SUCCESS; +} + +StatusCode CaloTowerGeometrySvc::f_setupTowerGridProj(const CaloDetDescrElement* pCaloDDE,std::ofstream& logger) +{ + // projective readout calos - collect geometrical variables + double cEtaPos(pCaloDDE->eta_raw()); // projective cell center in pseudorapidity + double cEtaWid(pCaloDDE->deta()); // projective cell width in pseudorapidity + double cPhiPos(pCaloDDE->phi_raw()); // projective cell center in azimuth + double cPhiWid(pCaloDDE->dphi()); // projective cell width in azimuth + + // check cell-tower overlap area fractions + uint_t kEta(static_cast<uint_t>(cEtaWid/m_towerEtaWidth+0.5)); kEta = kEta == 0 ? 1 : kEta; // fully contained cell may have 0 fragments (protection) + uint_t kPhi(static_cast<uint_t>(cPhiWid/m_towerPhiWidth+0.5)); kPhi = kPhi == 0 ? 1 : kPhi; + + // print out + if ( kEta > 1 || kPhi > 1 ) { + ATH_MSG_VERBOSE("Found cell [" << pCaloDDE->calo_hash() << "/0x" << std::hex << pCaloDDE->identify().get_compact() << std::dec << "] spawning several towers." + << " Neta = " << kEta << ", Nphi = " << kPhi ); + } + + // share cells + double cWght(1./((double)kEta*kPhi)); // area weight + double sEta(cEtaWid/((double)kEta)); // step size (pseudorapidity) + double sPhi(cPhiWid/((double)kPhi)); // step size (azimuth) + double oEta(cEtaPos-sEta/2.); // offset (pseudorapidity) + double oPhi(cPhiPos-sPhi/2.); // offset (azimuth) + + // loop over cell fragments + for ( uint_t ie(1); ie<=kEta; ++ie ) { + double ceta(oEta+((double)ie-0.5)*sEta); // eta of fragment + for ( uint_t ip(1); ip<=kPhi; ++ip ) { + double cphi(oPhi+((double)ip-0.5)*sPhi); // phi fragment + // tower index + index_t towerIdx(this->towerIndex(ceta,cphi)); + if ( isInvalidIndex(towerIdx) ) { + ATH_MSG_ERROR("Found invalid tower index for non-FCal cell (id,eta,phi) = (" << pCaloDDE->calo_hash() << "," << ceta << "," << cphi << ")"); + return StatusCode::FAILURE; + } // invalid tower index + // m_towerLookup[pCaloDDE->calo_hash()].emplace_back(towerIdx,cWght); // add to tower lookup + f_assign(pCaloDDE->calo_hash(),towerIdx,cWght); + if ( logger.is_open() ) { + double el(this->towerEta(towerIdx)-this->etaWidth()/2.); double eh(this->towerEta(towerIdx)+this->etaWidth()/2.); + double pl(this->towerPhi(towerIdx)-this->phiWidth()/2.); double ph(this->towerPhi(towerIdx)+this->phiWidth()/2.); + if ( cEtaPos >= el && cEtaPos <= eh && cPhiPos >= pl && cPhiPos <= ph ) { + logger << CaloRec::Helpers::fmtMsg("Cell [%6zu] at (%6.3f,%6.3f) in Sampling %10.10s contributes to tower [%5zu] at ([%6.3f,%6.3f],[%6.3f,%6.3f]) with weight %6.4f [IN_BOUNDS]", + (size_t)pCaloDDE->calo_hash(),cEtaPos,cPhiPos,CaloRec::Lookup::getSamplingName(pCaloDDE->getSampling()).c_str(),towerIdx,el,eh,pl,ph,cWght) << std::endl; + } else { + logger << CaloRec::Helpers::fmtMsg("Cell [%6zu] at (%6.3f,%6.3f) in Sampling %10.10s contributes to tower [%5zu] at ([%6.3f,%6.3f],[%6.3f,%6.3f]) with weight %6.4f [OUT_OF_BOUNDS]", + (size_t)pCaloDDE->calo_hash(),cEtaPos,cPhiPos,CaloRec::Lookup::getSamplingName(pCaloDDE->getSampling()).c_str(),towerIdx,el,eh,pl,ph,cWght) << std::endl; + } + } // debugging central region + } // phi fragment loop + } // eta fragment loop + return StatusCode::SUCCESS; +} + +//------// +// Fill // +//------// + +double CaloTowerGeometrySvc::f_assign(IdentifierHash cellHash,index_t towerIdx,double wght) +{ + // check if cell-tower already related + uint_t cidx(static_cast<uint_t>(cellHash)); + for ( element_t& elm : m_towerLookup.at(cidx) ) { + if ( towerIndex(elm) == towerIdx ) { std::get<1>(elm) += wght; return cellWeight(elm); } + } + // not yet related + m_towerLookup[cidx].emplace_back(towerIdx,wght); + return cellWeight(m_towerLookup.at(cidx).back()); +} + +//--------// +// Access // +//--------// + +StatusCode CaloTowerGeometrySvc::access(const CaloCell* pCell,std::vector<index_t>& towerIdx,std::vector<double>& towerWghts) const +{ return this->access(f_caloDDE(pCell)->calo_hash(),towerIdx,towerWghts); } + +StatusCode CaloTowerGeometrySvc::access(IdentifierHash cellHash,std::vector<index_t>& towerIdx,std::vector<double>& towerWghts) const +{ + towerIdx.clear(); + towerWghts.clear(); + + uint_t cidx(static_cast<uint_t>(cellHash)); + + if ( cidx >= m_towerLookup.size() ) { + ATH_MSG_WARNING("Invalid cell hash index " << cellHash << ", corresponding index " << cidx << " not found in tower lookup"); + return StatusCode::SUCCESS; + } + + if ( towerIdx.capacity() < m_towerLookup.at(cidx).size() ) { towerIdx.reserve(m_towerLookup.at(cidx).size()); } + if ( towerWghts.capacity() < m_towerLookup.at(cidx).size() ) { towerWghts.reserve(m_towerLookup.at(cidx).size()); } + + for ( const auto& elm : m_towerLookup.at(cidx) ) { towerIdx.push_back(towerIndex(elm)); towerWghts.push_back(cellWeight(elm)); } + + return StatusCode::SUCCESS; +} + +CaloTowerGeometrySvc::elementvector_t CaloTowerGeometrySvc::getTowers(const CaloCell* pCell) const +{ return pCell != 0 ? this->getTowers(f_caloDDE(pCell)->calo_hash()) : elementvector_t(); } + +CaloTowerGeometrySvc::elementvector_t CaloTowerGeometrySvc::getTowers(IdentifierHash cellHash) const +{ + // check input + uint_t cidx(static_cast<uint_t>(cellHash)); + if ( cidx >= m_towerLookup.size() ) { + ATH_MSG_WARNING( CaloRec::Helpers::fmtMsg("invalid cell hash %6zu beyond range (max hash is %6zu)",cidx,m_maxCellHash) ); + return elementvector_t(); + } else { + return m_towerLookup.at(cidx); + } +} + +//-----------------------// +// Tower Geometry Helper // +//-----------------------// + +double CaloTowerGeometrySvc::cellWeight(IdentifierHash cellHash,index_t towerIdx) const +{ + index_t cidx(static_cast<uint_t>(cellHash)); + double cwght(0.); + + if ( cidx < m_towerLookup.size() ) { + for ( auto elm : m_towerLookup.at(cidx) ) { + if ( towerIndex(elm) == towerIdx ) { cwght = cellWeight(elm); break; } + } + } + return cwght; +} + +//---------------// +// Index Helpers // +//---------------// + +CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::etaIndex(IdentifierHash cellHash) const +{ + const auto cdde = f_caloDDE(cellHash); + return cdde != 0 ? etaIndex(cdde->eta()) : invalidIndex(); +} + +CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::etaIndex(double eta) const +{ + return eta >= m_towerEtaMin && eta <= m_towerEtaMax + ? index_t(std::min(static_cast<uint_t>((eta-m_towerEtaMin)/m_towerEtaWidth),m_towerEtaBins-1)) + : invalidIndex(); +} + +CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::phiIndex(IdentifierHash cellHash) const +{ + const auto cdde = f_caloDDE(cellHash); + return cdde != 0 ? phiIndex(cdde->phi()) : invalidIndex(); +} + +CaloTowerGeometrySvc::index_t CaloTowerGeometrySvc::phiIndex(double phi) const +{ + double dphi(CaloPhiRange::diff(phi,m_towerPhiMin)); + return dphi >= m_towerPhiMin && dphi <= m_towerPhiMax + ? index_t(std::min(static_cast<uint_t>((phi-m_towerPhiMin)/m_towerPhiWidth),m_towerPhiBins-1)) + : invalidIndex(); +} diff --git a/Calorimeter/CaloRec/src/components/CaloRec_entries.cxx b/Calorimeter/CaloRec/src/components/CaloRec_entries.cxx index 4ca13346c76443b425ba96669d377841c2776dcb..90657db39b7455bd8fc9202fc757f3ac8dbfa3f1 100644 --- a/Calorimeter/CaloRec/src/components/CaloRec_entries.cxx +++ b/Calorimeter/CaloRec/src/components/CaloRec_entries.cxx @@ -33,7 +33,9 @@ #include "CaloRec/CaloTowerxAODAlgoBase.h" #include "CaloRec/CaloTopoClusterFromTowerMaker.h" #include "CaloRec/CaloTopoClusterFromTowerCalibrator.h" - +#include "CaloRec/CaloTopoClusterFromTowerMonitor.h" +#include "CaloRec/CaloTowerGeometrySvc.h" +#include "CaloRec/CaloTopoClusterTowerMerger.h" #include "GaudiKernel/DeclareFactoryEntries.h" @@ -57,6 +59,8 @@ DECLARE_ALGORITHM_FACTORY( CaloClusterCellLinksUpdater ) DECLARE_ALGORITHM_FACTORY( CaloTowerxAODFromCells ) DECLARE_ALGORITHM_FACTORY( CaloTowerxAODFromClusters ) DECLARE_ALGORITHM_FACTORY( CaloTowerxAODAlgoBase ) +DECLARE_ALGORITHM_FACTORY( CaloTopoClusterFromTowerMonitor ) + DECLARE_TOOL_FACTORY ( CaloTopoClusterFromTowerMaker ) DECLARE_TOOL_FACTORY ( CaloTopoClusterFromTowerCalibrator ) @@ -96,6 +100,7 @@ DECLARE_FACTORY_ENTRIES(CaloRec) { DECLARE_ALGORITHM( CaloTowerxAODAlgoBase ) DECLARE_ALGORITHM( CaloTowerxAODFromCells ) DECLARE_ALGORITHM( CaloTowerxAODFromClusters ) + DECLARE_ALGORITHM( CaloTopoClusterFromTowerMonitor ) DECLARE_TOOL( CaloTopoClusterFromTowerMaker ) DECLARE_TOOL( CaloTopoClusterFromTowerCalibrator ) @@ -116,3 +121,7 @@ DECLARE_FACTORY_ENTRIES(CaloRec) { DECLARE_TOOL( CaloCellFastCopyTool ) DECLARE_TOOL( CaloClusterSnapshot ) } + +DECLARE_COMPONENT( CaloTowerGeometrySvc ) +DECLARE_COMPONENT( CaloTopoClusterTowerMerger ) + diff --git a/Control/AthenaMonitoring/python/DQMonFlags.py b/Control/AthenaMonitoring/python/DQMonFlags.py index e6a15b4c3a7b9fe0778cc7b6d2eef934fee0c6be..e624702ee23d8125eb9ba4c5659a2bc8a2aa8d00 100644 --- a/Control/AthenaMonitoring/python/DQMonFlags.py +++ b/Control/AthenaMonitoring/python/DQMonFlags.py @@ -398,12 +398,14 @@ class enableLumiAccess(JobProperty): StoredValue=True list+=[enableLumiAccess] -class excludeFromCleaning(JobProperty): - """ Tools matching regexes in this list will not have event cleaning tool set up """ +class includeInCleaning(JobProperty): + """ Tools matching regexes in this list will have event cleaning tool set up """ statusOn=True allowedTypes=['list'] - StoredValue=['.*LAr.*', '.*Tile.*', '.*SCT.*', 'DQTDataFlowMon'] -list+=[excludeFromCleaning] + StoredValue=[ '.*JetMonitoring.*', '.*METMonTool.*', '.*tauMonTool.*', + '.*DQTGlobalWZFinder.*', '.*jetTagMon.*', '.*phMonTool.*', + '.*elMonTool.*', '.*fwdMonTool.*' ] +list+=[includeInCleaning] class specialCleaningConfiguration(JobProperty): """ Special event cleaning configurations (no regexes) """ diff --git a/Control/AthenaMonitoring/share/DQMonFlagsConfig_jobOptions.py b/Control/AthenaMonitoring/share/DQMonFlagsConfig_jobOptions.py index 5902d1127ad6b8c7b15005413f60041169975e42..47dfe8eb7566cd989a145aeb0de3e5e46f53391d 100644 --- a/Control/AthenaMonitoring/share/DQMonFlagsConfig_jobOptions.py +++ b/Control/AthenaMonitoring/share/DQMonFlagsConfig_jobOptions.py @@ -452,7 +452,7 @@ else: local_logger.info("Stream-Aware monitoring is turned OFF") # If data type is '*comm' disable ATLAS Ready filter by default -if (rec.projectName.get_Value().endswith('_comm') and +if (rec.projectName.get_Value().endswith('comm') and not DQMonFlags.disableAtlasReadyFilter() ): local_logger.info("This is a commissioning project tag, will attempt to disable ATLAS Ready filter for monitoring tools. To really enable it, use DQMonFlags.disableAtlasReadyFilter.set_Value_and_Lock(False).") diff --git a/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py b/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py index aef73735a8d4cf4548e30035f3bc50fb8a282ccf..1ce2256cbbfd3a0b4524bac6e47c50c27c9e3ddb 100644 --- a/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py +++ b/Control/AthenaMonitoring/share/DataQualitySteering_jobOptions.py @@ -273,8 +273,8 @@ if DQMonFlags.doMonitoring(): if rec.triggerStream()=='express': local_logger.info('Stream is express and we will add ready tool for %s', tool) tool.FilterTools += [monAtlasReadyFilterTool] - # unless prevented: configure a generic event cleaning tool - if not athenaCommonFlags.isOnline() and not any(re.match(_, tool.name()) for _ in DQMonFlags.excludeFromCleaning()): + # if requested: configure a generic event cleaning tool + if not athenaCommonFlags.isOnline() and any(re.match(_, tool.name()) for _ in DQMonFlags.includeInCleaning()): if tool.name() in DQMonFlags.specialCleaningConfiguration(): config_ = DQMonFlags.specialCleaningConfiguration()[tool.name()].copy() for _ in config_: diff --git a/Control/PileUpComps/src/PileUpEventLoopMgr.cxx b/Control/PileUpComps/src/PileUpEventLoopMgr.cxx index 8dc595019377db7e853d0f07b28456648f847628..dfc6788a6327b55927933b5e6d14ac460c54a088 100644 --- a/Control/PileUpComps/src/PileUpEventLoopMgr.cxx +++ b/Control/PileUpComps/src/PileUpEventLoopMgr.cxx @@ -498,7 +498,7 @@ StatusCode PileUpEventLoopMgr::nextEvent(int maxevt) std::unique_ptr< xAOD::EventAuxInfo > pxAODEventAuxInfo(new xAOD::EventAuxInfo()); std::unique_ptr< xAOD::EventInfo > pxAODEventInfo( new xAOD::EventInfo()); pxAODEventInfo->setStore( pxAODEventAuxInfo.get() ); - CHECK(m_xAODCnvTool->convert( pOverEvent, pxAODEventInfo.get(), false, false )); + CHECK(m_xAODCnvTool->convert( pOverEvent, pxAODEventInfo.get(), false, false, m_isEventOverlayJob)); // Before the record, keep a pointer to the EventInfo object, to be able // to add ElementLinks to it afterwards. xAOD::EventInfo* pLocalXAODEventInfo = pxAODEventInfo.get(); diff --git a/DataQuality/DataQualityTools/DataQualityTools/DQTGlobalWZFinderTool.h b/DataQuality/DataQualityTools/DataQualityTools/DQTGlobalWZFinderTool.h index bfee2fe59dbc366f1bab9f922ea2423cadf3a659..35ee98923d0535f3c344d86a4fd5dbdf246f1d14 100644 --- a/DataQuality/DataQualityTools/DataQualityTools/DQTGlobalWZFinderTool.h +++ b/DataQuality/DataQualityTools/DataQualityTools/DQTGlobalWZFinderTool.h @@ -22,7 +22,10 @@ #include "TrigDecisionTool/TrigDecisionTool.h" #include "TrigEgammaMatchingTool/ITrigEgammaMatchingTool.h" -#include "xAODEventInfo/EventInfo.h" + +#include "PATInterfaces/ISystematicsTool.h" +#include <PATInterfaces/SystematicRegistry.h> +#include <PATInterfaces/SystematicVariation.h> #include "TMath.h" #include <string> @@ -33,6 +36,11 @@ class TProfile; class TH1F_LW; class TH2F_LW; +namespace xAOD{ + class EventInfo_v1; typedef EventInfo_v1 EventInfo; + class TruthParticle_v1; typedef TruthParticle_v1 TruthParticle; +} + namespace CP { class IMuonSelectionTool; class IIsolationSelectionTool; @@ -66,20 +74,41 @@ private: void doMuonTriggerTP(const xAOD::Muon* , const xAOD::Muon*); void doMuonTruthEff(std::vector<const xAOD::Muon*>&); void doMuonLooseTP(std::vector<const xAOD::Muon*>& goodmuonsZ, const xAOD::Vertex* pVtx); + void doMuonInDetTP(std::vector<const xAOD::Muon*>& goodmuonsZ, const xAOD::Vertex* pVtx); -//----- Electron START -----// - void doEleTriggerTP(const xAOD::Electron*,const xAOD::Electron*); + //----- Electron START -----// + void doEleTriggerTP(const xAOD::Electron* el1, const xAOD::Electron* el2, bool os, bool ss); void doEleTP(const xAOD::Electron*, const xAOD::Electron*, const xAOD::Vertex*, const xAOD::EventInfo*, bool); + void doEleContainerTP(std::vector<const xAOD::Electron*>, std::vector<const xAOD::Electron*>); + bool goodElectrons(const xAOD::EventInfo*, const xAOD::Electron*, const xAOD::Vertex*, bool); + bool antiGoodElectrons(const xAOD::EventInfo* thisEventInfo, const xAOD::Electron* electron_itr, + const xAOD::Vertex* pVtx, bool isBad); + bool kinematicCuts(const xAOD::Electron*); ToolHandle<Trig::ITrigEgammaMatchingTool> m_elTrigMatchTool; - TH1F_LW *m_eltrigtp_matches; + TH1F *m_ZBosonCounter_El_os; + TH1F *m_ZBosonCounter_El_ss; + + TH1F_LW *m_eltrigtp_matches_os; + TH1F_LW *m_eltrigtp_matches_ss; + TH1F_LW *m_ele_tight_bad_os; TH1F_LW *m_ele_tight_bad_ss; TH1F_LW *m_ele_tight_good_os; TH1F_LW *m_ele_tight_good_ss; + TH1F_LW *m_ele_template_os; + TH1F_LW *m_ele_template_ss; + + //TH1F_LW *m_elContainertp_match; + TH1F_LW *m_elContainertp_nomatch; + TH1F_LW *m_ele_tight_passkine; + + TH1F_LW *m_totalSumWeights; + TH1F_LW *m_fiducialSumWeights_el; + TH1F_LW *m_fiducialSumWeights_mu; //----- Electron END ------// @@ -118,15 +147,11 @@ private: TH1F_LW *m_JPsiCounter_Mu; TH1F_LW *m_UpsilonCounter_Mu; - TH1F *m_ZBosonCounter_El; TH1F *m_ZBosonCounter_Mu; - TH1F *m_ZBosonCounter_Mu_CMS; //Trigger T&P TH1F_LW *m_mutrigtp_matches; - TH1F_LW *m_mutrigtp_matches_CMS; - //Reco T&P TH1F_LW *m_muloosetp_match_os; @@ -134,11 +159,11 @@ private: TH1F_LW *m_muloosetp_nomatch_os; TH1F_LW *m_muloosetp_nomatch_ss; - TH1F_LW *m_muloosetp_match_os_CMS; - TH1F_LW *m_muloosetp_match_ss_CMS; - TH1F_LW *m_muloosetp_nomatch_os_CMS; - TH1F_LW *m_muloosetp_nomatch_ss_CMS; - + // Inner detector T&P + TH1F_LW *m_mu_InDet_tp_match_os; + TH1F_LW *m_mu_InDet_tp_match_ss; + TH1F_LW *m_mu_InDet_tp_nomatch_os; + TH1F_LW *m_mu_InDet_tp_nomatch_ss; // MC truth TH1F_LW *m_mcmatch; @@ -174,7 +199,6 @@ private: std::string m_tracksName; Float_t m_electronEtCut; Float_t m_muonPtCut; - Float_t m_muonPtCut_CMS; Float_t m_metCut; Float_t m_zCutLow; diff --git a/DataQuality/DataQualityTools/src/DQTGlobalWZFinderTool.cxx b/DataQuality/DataQualityTools/src/DQTGlobalWZFinderTool.cxx index fd9479f11090f5a86c4c5d9311a6c596659da9d9..740e1dee82af254ebf30d80d607b2287553b6164 100644 --- a/DataQuality/DataQualityTools/src/DQTGlobalWZFinderTool.cxx +++ b/DataQuality/DataQualityTools/src/DQTGlobalWZFinderTool.cxx @@ -72,7 +72,6 @@ DQTGlobalWZFinderTool::DQTGlobalWZFinderTool(const std::string & type, m_tracksName("InDetTrackParticles"), //Kshort m_electronEtCut(25), m_muonPtCut(25), - m_muonPtCut_CMS(30), m_metCut(25), m_zCutLow(66.0), m_zCutHigh(116.0), @@ -180,9 +179,9 @@ StatusCode DQTGlobalWZFinderTool::bookHistogramsRecurrent() failure |= registerHist(fullPathDQTGlobalWZFinder, m_mu_lb = new TProfile("m_mu_lb", "#mu", 1, m_this_lb-0.5, m_this_lb+0.5), lumiBlock, ATTRIB_UNMANAGED, "merge").isFailure(); failure |= registerHist(fullPathDQTGlobalWZFinder, m_Z_ee_trig_ps = new TProfile("m_Z_ee_trig_ps", "Z->ee trigger PS", 1, m_this_lb-0.5, m_this_lb+0.5), lumiBlock, ATTRIB_UNMANAGED, "merge").isFailure(); failure |= registerHist(fullPathDQTGlobalWZFinder, m_Z_mm_trig_ps = new TProfile("m_Z_mm_trig_ps", "Z->#mu#mu trigger PS", 1, m_this_lb-0.5, m_this_lb+0.5), lumiBlock, ATTRIB_UNMANAGED, "merge").isFailure(); - failure |= registerHist(fullPathDQTGlobalWZFinder, m_ZBosonCounter_El = new TH1F("m_Z_Counter_el","Z #rightarrow ee Count per Lumi Block", 1, m_this_lb-0.5, m_this_lb+0.5), lumiBlock, ATTRIB_UNMANAGED, "merge").isFailure(); + failure |= registerHist(fullPathDQTGlobalWZFinder, m_ZBosonCounter_El_os = new TH1F("m_Z_Counter_el_os","Z #rightarrow ee Count per Lumi Block", 1, m_this_lb-0.5, m_this_lb+0.5), lumiBlock, ATTRIB_UNMANAGED, "merge").isFailure(); + failure |= registerHist(fullPathDQTGlobalWZFinder, m_ZBosonCounter_El_ss = new TH1F("m_Z_Counter_el_ss","Z #rightarrow ee Count per Lumi Block", 1, m_this_lb-0.5, m_this_lb+0.5), lumiBlock, ATTRIB_UNMANAGED, "merge").isFailure(); failure |= registerHist(fullPathDQTGlobalWZFinder, m_ZBosonCounter_Mu = new TH1F("m_Z_Counter_mu","Z #rightarrow #mu#mu Count per Lumi Block", 1, m_this_lb-0.5, m_this_lb+0.5), lumiBlock, ATTRIB_UNMANAGED, "merge").isFailure(); - failure |= registerHist(fullPathDQTGlobalWZFinder, m_ZBosonCounter_Mu_CMS = new TH1F("m_Z_Counter_mu_CMS","Z #rightarrow #mu#mu Count per Lumi Block (CMS cuts)", 1, m_this_lb-0.5, m_this_lb+0.5), lumiBlock, ATTRIB_UNMANAGED, "merge").isFailure(); if (!failure) { m_livetime_lb->Fill(m_this_lb, lbAverageLivefraction()); @@ -278,7 +277,6 @@ bool DQTGlobalWZFinderTool::bookDQTGlobalWZFinderTool() // T&P trigger rate failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_mutrigtp_matches = TH1F_LW::create("m_mutrigtp_matches", "Muon trigger TP stats", 3, -0.5, 2.5), lumiBlock).isFailure(); - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_mutrigtp_matches_CMS = TH1F_LW::create("m_mutrigtp_matches_CMS", "Muon trigger TP stats (CMS cuts)", 3, -0.5, 2.5), lumiBlock).isFailure(); // T&P muon eff failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_muloosetp_match_os = TH1F_LW::create("m_muloosetp_match_os", "Muon loose TP match OS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); @@ -286,20 +284,36 @@ bool DQTGlobalWZFinderTool::bookDQTGlobalWZFinderTool() failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_muloosetp_nomatch_os = TH1F_LW::create("m_muloosetp_nomatch_os", "Muon loose TP nomatch OS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_muloosetp_nomatch_ss = TH1F_LW::create("m_muloosetp_nomatch_ss", "Muon loose TP nomatch SS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_muloosetp_match_os_CMS = TH1F_LW::create("m_muloosetp_match_os_CMS", "Muon loose TP match OS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_muloosetp_match_ss_CMS = TH1F_LW::create("m_muloosetp_match_ss_CMS", "Muon loose TP match SS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_muloosetp_nomatch_os_CMS = TH1F_LW::create("m_muloosetp_nomatch_os_CMS", "Muon loose TP nomatch OS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_muloosetp_nomatch_ss_CMS = TH1F_LW::create("m_muloosetp_nomatch_ss_CMS", "Muon loose TP nomatch SS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); - + // T&P muon inner detector + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_mu_InDet_tp_match_os = TH1F_LW::create("m_mu_InDet_tp_match_os", "Muon inner detector TP match OS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_mu_InDet_tp_match_ss = TH1F_LW::create("m_mu_InDet_tp_match_ss", "Muon inner detector TP match SS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_mu_InDet_tp_nomatch_os = TH1F_LW::create("m_mu_InDet_tp_nomatch_os", "Muon inner detector TP nomatch OS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_mu_InDet_tp_nomatch_ss = TH1F_LW::create("m_mu_InDet_tp_nomatch_ss", "Muon inner detector TP nomatch SS", nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); // Clone of above but for electrons - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_eltrigtp_matches = TH1F_LW::create("m_eltrigtp_matches", "Electron trigger TP stats", 3, -0.5, 2.5), lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_eltrigtp_matches_os = TH1F_LW::create("m_eltrigtp_matches_os", "Electron trigger TP stats", 3, -0.5, 2.5), lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_eltrigtp_matches_ss = TH1F_LW::create("m_eltrigtp_matches_ss", "Electron trigger TP stats", 3, -0.5, 2.5), lumiBlock).isFailure(); // T&P electron eff - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_bad_os = TH1F_LW::create("m_ele_tight_bad_os", "1tight 1bad os",nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_bad_ss = TH1F_LW::create("m_ele_tight_bad_ss", "1tight 1bad ss",nzbins, m_zCutLow*GeV, m_zCutHigh*GeV), lumiBlock).isFailure(); - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_good_os = TH1F_LW::create("m_ele_tight_good_os","1tight 1good os",nzbins,m_zCutLow*GeV, m_zCutHigh*GeV),lumiBlock).isFailure(); - failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_good_ss = TH1F_LW::create("m_ele_tight_good_ss","1tight 1good ss",nzbins,m_zCutLow*GeV, m_zCutHigh*GeV),lumiBlock).isFailure(); + double m_zCutHigh_elTP = 250; + double m_zCutLow_elTP = 66; + int nzbins_elTP = int(ceilf(m_zCutHigh_elTP - m_zCutLow_elTP)); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_bad_os = TH1F_LW::create("m_ele_tight_bad_os" , "1tight 1bad os" ,nzbins_elTP, m_zCutLow_elTP*GeV, m_zCutHigh_elTP*GeV), + lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_bad_ss = TH1F_LW::create("m_ele_tight_bad_ss" , "1tight 1bad ss" ,nzbins_elTP, m_zCutLow_elTP*GeV, m_zCutHigh_elTP*GeV), + lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_good_os = TH1F_LW::create("m_ele_tight_good_os" , "1tight 1good os",nzbins_elTP, m_zCutLow_elTP*GeV, m_zCutHigh_elTP*GeV), + lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_good_ss = TH1F_LW::create("m_ele_tight_good_ss" , "1tight 1good ss",nzbins_elTP, m_zCutLow_elTP*GeV, m_zCutHigh_elTP*GeV), + lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_template_os = TH1F_LW::create("m_ele_template_os" , "template os" ,nzbins_elTP, m_zCutLow_elTP*GeV, m_zCutHigh_elTP*GeV), + lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_template_ss = TH1F_LW::create("m_ele_template_ss" , "template ss" ,nzbins_elTP, m_zCutLow_elTP*GeV, m_zCutHigh_elTP*GeV), + lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_elContainertp_nomatch = TH1F_LW::create("m_elContainertp_nomatch" , "m_elContainertp_nomatch" ,nzbins_elTP, m_zCutLow_elTP*GeV, + m_zCutHigh_elTP*GeV), lumiBlock).isFailure(); + failure = failure | registerHist(fullPathDQTGlobalWZFinder, m_ele_tight_passkine = TH1F_LW::create("m_ele_tight_passkine" , "m_ele_tight_passkine" ,nzbins_elTP, m_zCutLow_elTP*GeV, + m_zCutHigh_elTP*GeV), lumiBlock).isFailure(); if (thisEventInfo->eventType(xAOD::EventInfo::IS_SIMULATION)) { @@ -352,9 +366,8 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() m_evtWeight = thisEventInfo->mcEventWeight(); ATH_MSG_DEBUG("Event Weight: " << m_evtWeight); } - - //Get MET - + + //Get MET Double_t phiMet = 0, metMet = 0; // const MissingET *missET; const xAOD::MissingETContainer *missETcont(0); @@ -381,10 +394,7 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() ATH_MSG_DEBUG(" MET = " << metMet << " and met phi = " << phiMet); - //Get Electrons - - // const ElectronContainer* elecTES = 0; const xAOD::ElectronContainer* elecTES = 0; if ( evtStore()->contains<xAOD::ElectronContainer>(m_electronContainerName) ) { sc=evtStore()->retrieve( elecTES, m_electronContainerName); @@ -403,7 +413,6 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() ATH_MSG_DEBUG("ElectronContainer successfully retrieved"); //Get Muons - // const Analysis::MuonContainer* muons = 0; const xAOD::MuonContainer* muons = 0; if(evtStore()->contains<xAOD::MuonContainer>(m_muonContainerName)){ sc = evtStore()->retrieve(muons,m_muonContainerName); @@ -426,12 +435,7 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() std::vector<Int_t> goodmuonJPsicharge; //get primary vertex info - //const VxContainer *m_vertices; const xAOD::VertexContainer* vertices(0); - //bool vertexCut = false; - - //EP CHECK( m_xaodConverter.retrieve() ); - const xAOD::Vertex* pVtx(0); if ( evtStore()->contains<xAOD::VertexContainer>(m_VxPrimContainerName)) { sc = evtStore()->retrieve(vertices,m_VxPrimContainerName); @@ -492,7 +496,7 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() m_ele_Et->Fill((*itr)->pt()/GeV, m_evtWeight); m_ele_Eta->Fill((*itr)->eta(), m_evtWeight); goodelectrons.push_back(*itr); - } + } } @@ -501,26 +505,25 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() Int_t MuJPsi_N = 0; ATH_MSG_DEBUG("Start muon selection"); - xAOD::MuonContainer::const_iterator muonItr; - for (muonItr=muons->begin(); muonItr != muons->end(); ++muonItr) { - Float_t minptCutJPsi(1.0*CLHEP::GeV); - auto muTrk = (*muonItr)->primaryTrackParticle(); - float d0sig; - if (!muTrk) { - ATH_MSG_WARNING("No muon track! " << thisEventInfo->runNumber() << " " << thisEventInfo->eventNumber()); - continue; - } - try { - d0sig = xAOD::TrackingHelpers::d0significance(muTrk, thisEventInfo->beamPosSigmaX(), thisEventInfo->beamPosSigmaY(), thisEventInfo->beamPosSigmaXY()); - } catch (...) { + for (xAOD::MuonContainer::const_iterator muonItr=muons->begin(); muonItr != muons->end(); ++muonItr){ + Float_t minptCutJPsi(1.0*CLHEP::GeV); + auto muTrk = (*muonItr)->primaryTrackParticle(); + float d0sig; + if (!muTrk) { + ATH_MSG_WARNING("No muon track! " << thisEventInfo->runNumber() << " " << thisEventInfo->eventNumber()); + continue; + } + try { + d0sig = xAOD::TrackingHelpers::d0significance(muTrk, thisEventInfo->beamPosSigmaX(), thisEventInfo->beamPosSigmaY(), thisEventInfo->beamPosSigmaXY()); + } catch (...) { ATH_MSG_DEBUG("Invalid beamspot - muon"); - try { - d0sig = xAOD::TrackingHelpers::d0significance(muTrk); - } catch (...) { - ATH_MSG_WARNING("Ridiculous exception thrown - muon"); - continue; - } - } + try { + d0sig = xAOD::TrackingHelpers::d0significance(muTrk); + } catch (...) { + ATH_MSG_WARNING("Ridiculous exception thrown - muon"); + continue; + } + } ATH_MSG_DEBUG("Muon accept: " << m_muonSelectionTool->accept(**muonItr)); @@ -589,13 +592,15 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() } doMuonLooseTP(goodmuonsZ, pVtx); + doMuonInDetTP(goodmuonsZ, pVtx); doEleTP(leadingAllEle, subleadingAllEle, pVtx, thisEventInfo, isBad); + doEleContainerTP(allElectrons, goodelectrons); + // Sort Candidates by Pt - const xAOD::Electron* leadingEle(0); - const xAOD::Electron* subleadingEle(0); - const xAOD::Muon* leadingMuZ(0); - const xAOD::Muon* subleadingMuZ(0); + const xAOD::Electron* subleadingEle(0); + const xAOD::Muon* leadingMuZ(0); + const xAOD::Muon* subleadingMuZ(0); CLHEP::HepLorentzVector leadingMuJPsi; CLHEP::HepLorentzVector subleadingMuJPsi; @@ -608,16 +613,18 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() ATH_MSG_DEBUG("Beginning ele loop"); for (UInt_t iEle = 0; iEle < goodelectrons.size(); iEle++) { - Float_t pt = goodelectrons[iEle]->pt(); - ATH_MSG_DEBUG("Ele pt " << pt); - if (! leadingEle || pt > leadingEle->pt()) { - subleadingEle = leadingEle; - leadingEle = goodelectrons[iEle]; - } - else if (! subleadingEle || pt > subleadingEle->pt()) { - subleadingEle = goodelectrons[iEle]; - } + Float_t pt = goodelectrons[iEle]->pt(); + ATH_MSG_DEBUG("Ele pt " << pt); + if (! leadingEle || pt > leadingEle->pt()) { + subleadingEle = leadingEle; + leadingEle = goodelectrons[iEle]; + } + else if (! subleadingEle || pt > subleadingEle->pt()) { + subleadingEle = goodelectrons[iEle]; + } } + + ATH_MSG_DEBUG("Done ele loop"); ATH_MSG_DEBUG("Start mu Z loop"); for (UInt_t iMu = 0; iMu < goodmuonsZ.size(); iMu++) { @@ -665,57 +672,62 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() ATH_MSG_DEBUG("Zee found"); TLorentzVector Zee = (leadingEle->p4() + subleadingEle->p4()); Float_t mass = Zee.M(); - Int_t Zeecharge = leadingEle->charge() + subleadingEle->charge(); + Int_t Zeecharge = leadingEle->charge() + subleadingEle->charge(); bool ignoreTrig = trigChainsArePassed(m_Z_ee_trigger) || !m_doTrigger; - if (mass > m_zCutLow*GeV && mass < m_zCutHigh*GeV ) { - m_Z_Q_ele->Fill(Zeecharge, m_evtWeight); - ATH_MSG_DEBUG( "Found a Z to ee candidate! Mass = " << mass << ", and charge = " << Zeecharge ); - if (Zeecharge == 0){ - if(ignoreTrig){ - m_Z_mass_opsele->Fill(mass, m_evtWeight); - m_ZBosonCounter_El->Fill(m_this_lb, m_evtWeight); - ++m_ZBosonCounterSBG_El[0]; - } - if(m_doTrigger){ - doEleTriggerTP(leadingEle, subleadingEle); - } - } else{ - if(ignoreTrig){ + bool inMassWindow = (mass > m_zCutLow*GeV && mass < m_zCutHigh*GeV); + bool os = false; + bool ss = false; + (Zeecharge == 0) ? (os = true) : (ss = true); + + if (inMassWindow){ + m_Z_Q_ele->Fill(Zeecharge, m_evtWeight); + ATH_MSG_DEBUG( "Found a Z to ee candidate! Mass = " << mass << ", and charge = " << Zeecharge ); + } + if(inMassWindow && os && ignoreTrig){ + m_Z_mass_opsele->Fill(mass, m_evtWeight); + m_ZBosonCounter_El_os->Fill(m_this_lb, m_evtWeight); + ++m_ZBosonCounterSBG_El[0]; + } + if(inMassWindow && ss && ignoreTrig){ m_Z_mass_ssele->Fill(mass, m_evtWeight); + m_ZBosonCounter_El_ss->Fill(m_this_lb, m_evtWeight); } - } + if(inMassWindow && m_doTrigger){ + doEleTriggerTP(leadingEle, subleadingEle, os, ss); } } - if (isZmumu) { + + if (isZmumu){ ATH_MSG_DEBUG("Zmumu found"); TLorentzVector Zmumu = leadingMuZ->p4() + subleadingMuZ->p4(); Float_t mass = Zmumu.M(); Int_t Zmumucharge = leadingMuZ->charge() + subleadingMuZ->charge(); // potentially ignore trigger... bool oktrig = trigChainsArePassed(m_Z_mm_trigger) || !m_doTrigger; - if (mass > m_zCutLow*GeV && mass < m_zCutHigh*GeV){ - ATH_MSG_DEBUG("Found a Z to mumu candidate! Mass = " << mass << ", and charge = " << Zmumucharge); - if (Zmumucharge == 0) { - if (oktrig) { - m_Z_Q_mu->Fill(Zmumucharge, m_evtWeight); - m_Z_mass_opsmu->Fill(mass, m_evtWeight); - m_ZBosonCounter_Mu->Fill(m_this_lb, m_evtWeight); - if(leadingMuZ->pt() > m_muonPtCut_CMS && subleadingMuZ->pt() > m_muonPtCut_CMS){ - m_ZBosonCounter_Mu_CMS->Fill(m_this_lb, m_evtWeight); - } - ++m_ZBosonCounterSBG_Mu[0]; - } - else { ATH_MSG_DEBUG("Trigger failure!"); } - if (m_doTrigger) { - doMuonTriggerTP(leadingMuZ, subleadingMuZ); - } - } else { - if (oktrig) { - m_Z_mass_ssmu->Fill(mass, m_evtWeight); - } - } - } + bool inMassWindow = (mass > m_zCutLow*GeV && mass < m_zCutHigh*GeV); + bool os = false; + bool ss = false; + (Zmumucharge == 0) ? (os = true) : (ss = true); + + if(inMassWindow){ + m_Z_Q_mu->Fill(Zmumucharge, m_evtWeight); + ATH_MSG_DEBUG("Found a Z to mumu candidate! Mass = " << mass << ", and charge = " << Zmumucharge); + } + if(inMassWindow && os && oktrig){ + m_Z_mass_opsmu->Fill(mass, m_evtWeight); + m_ZBosonCounter_Mu->Fill(m_this_lb, m_evtWeight); + ++m_ZBosonCounterSBG_Mu[0]; + } + if(inMassWindow && os && !oktrig){ + ATH_MSG_DEBUG("Trigger failure!"); + } + if(inMassWindow && os && m_doTrigger){ + doMuonTriggerTP(leadingMuZ, subleadingMuZ); + } + if(inMassWindow && ss && oktrig){ + m_Z_mass_ssmu->Fill(mass, m_evtWeight); + } } //JPsi and Upsilon counter @@ -792,16 +804,15 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() Float_t px = leadingEle->p4().Px(); Float_t py = leadingEle->p4().Py(); Float_t pz = leadingEle->p4().Pz(); - Float_t p = sqrt(px*px+py*py+pz*pz); - Float_t et = leadingEle->e()*leadingEle->pt()/p; - Float_t mt = sqrt(2*(et*metMet-px*metx-py*mety)); - - if (mt > mtCut) - { - m_W_pt_v_met_ele->Fill(leadingEle->pt(), metMet, m_evtWeight); - m_W_mt_ele->Fill(mt, m_evtWeight); - ATH_MSG_DEBUG("Found a W to enu candidate! M_T = " << mt << ", and MET = " << metMet << ", and ele_pt = " << leadingEle->pt()); - } + Float_t p = sqrt(px*px+py*py+pz*pz); + Float_t et = leadingEle->e()*leadingEle->pt()/p; + Float_t mt = sqrt(2*(et*metMet-px*metx-py*mety)); + + if (mt > mtCut){ + m_W_pt_v_met_ele->Fill(leadingEle->pt(), metMet, m_evtWeight); + m_W_mt_ele->Fill(mt, m_evtWeight); + ATH_MSG_DEBUG("Found a W to enu candidate! M_T = " << mt << ", and MET = " << metMet << ", and ele_pt = " << leadingEle->pt()); + } } if (isWmunu) { @@ -821,6 +832,24 @@ StatusCode DQTGlobalWZFinderTool::fillHistograms() } } + + //for(int i=0; i<goodelectrons.size(); i++) delete goodelectrons[i]; + //for(int i=0; i<goodmuonsZ.size(); i++) delete goodmuonsZ[i]; + //for(int i=0; i<allElectrons.size(); i++) delete allElectrons[i]; + goodelectrons.clear(); + goodmuonsZ.clear(); + allElectrons.clear(); + + +/* + delete leadingEle; + delete subleadingEle; + delete leadingMuZ; + delete subleadingMuZ; + delete leadingAllEle; + delete subleadingAllEle; +*/ + return sc; } //end ifBeam @@ -910,8 +939,7 @@ StatusCode DQTGlobalWZFinderTool::procHistograms( ) } //------ Electron START ------// -void DQTGlobalWZFinderTool::doEleTriggerTP(const xAOD::Electron* el1, - const xAOD::Electron* el2) { +void DQTGlobalWZFinderTool::doEleTriggerTP(const xAOD::Electron* el1, const xAOD::Electron* el2, bool os, bool ss) { int matched = 0; std::vector<const xAOD::Electron*> electrons{el1, el2}; for (const auto el: electrons) { @@ -922,7 +950,10 @@ void DQTGlobalWZFinderTool::doEleTriggerTP(const xAOD::Electron* el1, } } } - m_eltrigtp_matches->Fill(matched,m_evtWeight); + + if(os) m_eltrigtp_matches_os->Fill(matched, m_evtWeight); + if(ss) m_eltrigtp_matches_ss->Fill(matched, m_evtWeight); + } void @@ -940,17 +971,16 @@ DQTGlobalWZFinderTool::doEleTP(const xAOD::Electron* leadingAllEle, auto p2(subleadingAllEle->p4()); Float_t mass = (p1+p2).M(); - bool leading_good = goodElectrons(thisEventInfo, leadingAllEle, pVtx, isBad); - bool subleading_good = goodElectrons(thisEventInfo, subleadingAllEle, pVtx, isBad); + bool leadingPassKinematics = kinematicCuts(leadingAllEle); + bool subleadPassKinematics = kinematicCuts(subleadingAllEle); + if(!leadingPassKinematics || !subleadPassKinematics) return; - // even if the probe is a bad electron, we still require it to not be in the gap - // the no gap is built into the good criterion anyway so don't need it for good electrons - bool leading_probe_nogap = fabs((leadingAllEle)->caloCluster()->etaBE(2)) > 1.37 && - fabs((leadingAllEle)->caloCluster()->etaBE(2)) < 1.52; + bool leading_good = goodElectrons(thisEventInfo, leadingAllEle, pVtx, isBad); + bool subleading_good = goodElectrons(thisEventInfo, subleadingAllEle, pVtx, isBad); - bool subleading_probe_nogap = fabs((subleadingAllEle)->caloCluster()->etaBE(2)) > 1.37 && - fabs((subleadingAllEle)->caloCluster()->etaBE(2)) < 1.52; + bool leading_antigood = antiGoodElectrons(thisEventInfo, leadingAllEle, pVtx, isBad); + bool subleading_antigood = antiGoodElectrons(thisEventInfo, subleadingAllEle, pVtx, isBad); // do trigger matching bool leading_trig = false; @@ -970,49 +1000,114 @@ DQTGlobalWZFinderTool::doEleTP(const xAOD::Electron* leadingAllEle, } // now start to do the selection - if( leadingAllEle->passSelection("LHTight") && leading_trig && leading_good ){ + if(leadingAllEle->passSelection("LHTight") && leading_trig && leading_good){ if(Zeecharge==0){ - if(subleading_good){ - m_ele_tight_good_os->Fill(mass); // leading tight, subleading good, opposite sign - }else{ - if(!subleading_probe_nogap) { - m_ele_tight_bad_os->Fill(mass); // leading tight, subleading fail, opposite sign - } - } - } else{ - if(subleading_good){ - m_ele_tight_good_ss->Fill(mass); // leading tight, subleading good, same sign - }else{ - if(!subleading_probe_nogap){ - m_ele_tight_bad_ss->Fill(mass); // leading tight, subleading fail, same sign - } - } - } - } - - if( subleadingAllEle->passSelection("LHTight") && subleading_trig && subleading_good ){ + (subleading_good) ? m_ele_tight_good_os->Fill(mass) : m_ele_tight_bad_os->Fill(mass); + if(subleading_antigood) m_ele_template_os->Fill(mass); + }else{ + (subleading_good) ? m_ele_tight_good_ss->Fill(mass) : m_ele_tight_bad_ss->Fill(mass); + if(subleading_antigood) m_ele_template_ss->Fill(mass); + } + } + + if(subleadingAllEle->passSelection("LHTight") && subleading_trig && subleading_good){ if(Zeecharge==0){ - if(leading_good){ - m_ele_tight_good_os->Fill(mass); // subleading tight, leading good, opposite sign - }else{ - if(!leading_probe_nogap){ - m_ele_tight_bad_os->Fill(mass); // subleading tight, leading fail, opposite sign - } - } - } else{ - if(leading_good){ - m_ele_tight_good_ss->Fill(mass); // subleading tight, leading good, same sign - }else{ - if(!leading_probe_nogap){ - m_ele_tight_bad_ss->Fill(mass); // subleading tight, leading fail, same sign - } - } + (leading_good) ? m_ele_tight_good_os->Fill(mass) : m_ele_tight_bad_os->Fill(mass); + if(leading_antigood) m_ele_template_os->Fill(mass); + }else{ + (leading_good) ? m_ele_tight_good_ss->Fill(mass) : m_ele_tight_bad_ss->Fill(mass); + if(leading_antigood) m_ele_template_ss->Fill(mass); } } + }// subleading pointer exixts }// leading pointer exists }// end doEleTP + +void DQTGlobalWZFinderTool::doEleContainerTP(std::vector<const xAOD::Electron*> allElectrons, std::vector<const xAOD::Electron*> goodelectrons) { + const xAOD::PhotonContainer* Photons(0); + evtStore()->retrieve(Photons, "Photons"); + if (!Photons) { + ATH_MSG_FATAL("Unable to retrieve photons to do electron T&P"); + return; + } + + for (const auto& tagEl : goodelectrons) { + bool matched = false; + for (const auto chain: m_Z_ee_trigger) { + if (m_elTrigMatchTool->match(tagEl, chain) || ! m_doTrigger) { + matched=true; + break; + } + } + + if (!matched) continue; + auto tagElp4(tagEl->p4()); + + if (tagEl->passSelection("LHTight")){ + for (const auto& el2 : allElectrons){ + if (el2 != tagEl && kinematicCuts(el2)){ + auto probeElp4(el2->p4()); + Float_t mass = (tagElp4+probeElp4).M(); + m_ele_tight_passkine->Fill(mass); + break; + } + } + } + + + for (const auto& photon : *Photons) { + auto photonp4(photon->p4()); + Float_t mass = (tagElp4+photonp4).M(); + + bool passPT = (photon->pt() > m_muonPtCut*GeV); + bool passEta = true; + if (fabs(photon->eta()) > 2.4) + passEta = false; + if (fabs(photon->eta()) > 1.37 && fabs(photon->eta()) < 1.52) + passEta = false; + //bool inMassWindow = (mass > m_zCutLow*GeV && mass < m_zCutHigh*GeV); + + if (!passPT || !passEta) // || !inMassWindow) + continue; + + for (const auto& el2 : allElectrons){ + // slightly relax pT cut for probe electron + bool passKinematics = true; + if (el2->pt() < (m_muonPtCut-2)*GeV) + passKinematics = false; + if (fabs((el2)->caloCluster()->etaBE(2)) > 2.4) + passKinematics = false; + if (fabs((el2)->caloCluster()->etaBE(2)) > 1.37 && fabs((el2)->caloCluster()->etaBE(2)) < 1.52) + passKinematics = false; + + double deltaR = (el2->p4()).DeltaR(photon->p4()); + if (!passKinematics || tagEl == el2 || deltaR < 0.1) + continue; + + m_elContainertp_nomatch->Fill(mass); + break; + + } + } + } +} + + +bool DQTGlobalWZFinderTool::kinematicCuts(const xAOD::Electron* electron){ + + bool isGood = true; + if(electron->pt() < m_muonPtCut*GeV) isGood = false; + + if(fabs((electron)->caloCluster()->etaBE(2)) > 2.4) isGood = false; + + if(fabs((electron)->caloCluster()->etaBE(2)) > 1.37 && + fabs((electron)->caloCluster()->etaBE(2)) < 1.52) isGood = false; + + return isGood; +} + bool DQTGlobalWZFinderTool::goodElectrons(const xAOD::EventInfo* thisEventInfo, const xAOD::Electron* electron_itr, const xAOD::Vertex* pVtx, @@ -1049,8 +1144,7 @@ bool DQTGlobalWZFinderTool::goodElectrons(const xAOD::EventInfo* thisEventInfo, fabs((elTrk->z0()+elTrk->vz()-pVtx->z())*std::sin(elTrk->theta())) < 0.5*mm && !isBad ){ // electron dead zone - if ( fabs((electron_itr)->caloCluster()->etaBE(2)) > 1.37 && - fabs((electron_itr)->caloCluster()->etaBE(2)) < 1.52 ){ + if (fabs((electron_itr)->caloCluster()->etaBE(2)) > 1.37 && fabs((electron_itr)->caloCluster()->etaBE(2)) < 1.52 ){ isGood = false; } else{ isGood = true; @@ -1059,7 +1153,51 @@ bool DQTGlobalWZFinderTool::goodElectrons(const xAOD::EventInfo* thisEventInfo, return isGood; } -//------ Electron END ------// + +bool DQTGlobalWZFinderTool::antiGoodElectrons(const xAOD::EventInfo* thisEventInfo, + const xAOD::Electron* electron_itr, + const xAOD::Vertex* pVtx, + bool isBad){ + bool antiGood = false; + Float_t m_electronEtCut = m_muonPtCut; + + bool passID = electron_itr->passSelection("LHLoose"); + bool passIso = m_isolationSelectionTool->accept(*electron_itr); + auto elTrk = (electron_itr)->trackParticle(); + + if (!elTrk) { + return false; + } + float d0sig; + try { + d0sig = xAOD::TrackingHelpers::d0significance(elTrk, thisEventInfo->beamPosSigmaX(), thisEventInfo->beamPosSigmaY(), thisEventInfo->beamPosSigmaXY()); + } catch (...) { + ATH_MSG_DEBUG("Invalid beamspot - electron"); + try { + d0sig = xAOD::TrackingHelpers::d0significance(elTrk); + } catch (...) { + ATH_MSG_WARNING("Ridiculous exception thrown - electron"); + return false; + } + } + + // pass basic selection, except ID+Isolation + if (((electron_itr)->pt() > m_electronEtCut*GeV) && + fabs((electron_itr)->caloCluster()->etaBE(2)) < 2.4 && + fabs(d0sig) < 5 && + pVtx && + fabs((elTrk->z0()+elTrk->vz()-pVtx->z())*std::sin(elTrk->theta())) < 0.5*mm && + !isBad) + { + if(fabs((electron_itr)->caloCluster()->etaBE(2)) > 1.37 && fabs((electron_itr)->caloCluster()->etaBE(2)) < 1.52){ + antiGood = false; + }else{ + if(!passID && !passIso) antiGood = true; + } + } + + return antiGood; +} // Compute trigger efficiencies @@ -1077,9 +1215,6 @@ void DQTGlobalWZFinderTool::doMuonTriggerTP(const xAOD::Muon* mu1, const xAOD::M } } m_mutrigtp_matches->Fill(matched,m_evtWeight); - if(mu1->pt() > m_muonPtCut_CMS && mu2->pt() > m_muonPtCut_CMS){ - m_mutrigtp_matches_CMS->Fill(matched,m_evtWeight); - } } void DQTGlobalWZFinderTool::doMuonTruthEff(std::vector<const xAOD::Muon*>& goodmuonsZ) { @@ -1142,14 +1277,8 @@ void DQTGlobalWZFinderTool::doMuonLooseTP(std::vector<const xAOD::Muon*>& goodmu ATH_MSG_DEBUG("MATCH WOOO, authors " << mu2->allAuthors()); if (trk->charge() != tagmu->charge()) { m_muloosetp_match_os->Fill(mass); - if(tagmu->pt() > m_muonPtCut_CMS && trk->pt() > m_muonPtCut_CMS){ - m_muloosetp_match_os_CMS->Fill(mass); - } } else { m_muloosetp_match_ss->Fill(mass); - if(tagmu->pt() > m_muonPtCut_CMS && trk->pt() > m_muonPtCut_CMS){ - m_muloosetp_match_ss_CMS->Fill(mass); - } } matched = true; break; @@ -1162,21 +1291,65 @@ void DQTGlobalWZFinderTool::doMuonLooseTP(std::vector<const xAOD::Muon*>& goodmu ATH_MSG_DEBUG("idtrk pt " << trk->pt()/GeV); if (trk->charge() != tagmu->charge()) { m_muloosetp_nomatch_os->Fill(mass); - if(tagmu->pt() > m_muonPtCut_CMS && trk->pt() > m_muonPtCut_CMS){ - m_muloosetp_nomatch_os_CMS->Fill(mass); - } } else { m_muloosetp_nomatch_ss->Fill(mass); - if(tagmu->pt() > m_muonPtCut_CMS && trk->pt() > m_muonPtCut_CMS){ - m_muloosetp_nomatch_ss_CMS->Fill(mass); - } } } } } } } - + + + +void DQTGlobalWZFinderTool::doMuonInDetTP(std::vector<const xAOD::Muon*>& goodmuonsZ, const xAOD::Vertex* pVtx) { + const xAOD::EventInfo* thisEventInfo; + StatusCode sc = evtStore()->retrieve(thisEventInfo); + const xAOD::TrackParticleContainer* msTracks(0); evtStore()->retrieve(msTracks, "ExtrapolatedMuonTrackParticles"); + if (!msTracks) { + ATH_MSG_FATAL("Unable to retrieve MS tracks to do muon T&P"); + return; + } + + for (const auto& tagmu : goodmuonsZ) { + bool matched = false; + for (const auto chain: m_Z_mm_trigger) { + if (m_muTrigMatchTool->match(tagmu, chain) || ! m_doTrigger) { + matched=true; + break; + } + } + + if (!matched) continue; + auto tagmup4(tagmu->p4()); + for (const auto& trk : *msTracks) { + if (trk->pt() < m_muonPtCut*GeV || fabs(trk->eta()) > m_muonMaxEta) continue; + + auto trkp4(trk->p4()); + Float_t mass = (tagmup4+trkp4).M(); + bool matched = false; + + if (mass < m_zCutLow*GeV || mass > m_zCutHigh*GeV) continue; + for (const auto& mu2 : goodmuonsZ) { + auto mslink = mu2->extrapolatedMuonSpectrometerTrackParticleLink(); + if (*(mslink.cptr()) == trk) { + (trk->charge() != tagmu->charge()) ? static_cast<void>(m_mu_InDet_tp_match_os->Fill(mass)) : static_cast<void>(m_mu_InDet_tp_match_ss->Fill(mass)); + matched = true; + break; + } + } + + if (!matched) + (trk->charge() != tagmu->charge()) ? static_cast<void>(m_mu_InDet_tp_nomatch_os->Fill(mass)) : static_cast<void>(m_mu_InDet_tp_nomatch_ss->Fill(mass)); + + } + } +} + + + + + //---------------------------------------------------------------------------------- StatusCode DQTGlobalWZFinderTool::checkHists(bool /* fromFinalize */) //---------------------------------------------------------------------------------- diff --git a/DataQuality/GoodRunsLists/Root/RegularFormula.cxx b/DataQuality/GoodRunsLists/Root/RegularFormula.cxx index 3e895e244679fda9138876c3419695ceea5bd3b3..f1ea555ca6179d1e7c6857fb9ab1f95052b385a4 100644 --- a/DataQuality/GoodRunsLists/Root/RegularFormula.cxx +++ b/DataQuality/GoodRunsLists/Root/RegularFormula.cxx @@ -75,6 +75,7 @@ Root::RegularFormula::parseExpression(const char* expression, TString& expr) TMsgLogger mylogger( "RegularFormula" ); mylogger << kINFO << "Now parsing regular expression : " << expression << GEndl; + mylogger << kINFO << "Please be aware that Cling errors are expected and aren't inherently a problem" << GEndl; TFormula analyzer("analyzer","1"); TObjArray* parArr = parStr.Tokenize(" "); diff --git a/DataQuality/ZLumiScripts/scripts/dqt_zlumi_alleff_HIST.py b/DataQuality/ZLumiScripts/scripts/dqt_zlumi_alleff_HIST.py index ecb4f90b5e0d2951ee40585e766dd2da7ca9b252..169c7671d6a75ac2b7fa0d3f01072d6deba6a3f7 100755 --- a/DataQuality/ZLumiScripts/scripts/dqt_zlumi_alleff_HIST.py +++ b/DataQuality/ZLumiScripts/scripts/dqt_zlumi_alleff_HIST.py @@ -2,29 +2,262 @@ # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration import sys, os, glob import ROOT - +import argparse +import math +from array import array +from DQUtils import fetch_iovs +ROOT.gROOT.SetBatch(ROOT.kTRUE) ROOT.gStyle.SetOptStat(0) -#ACCEPTANCE = 3.173927e-01 -ACCEPTANCE = 3.323224e-01 - -import argparse parser = argparse.ArgumentParser() parser.add_argument('infile', type=str, help='input HIST file') parser.add_argument('--out', type=str, help='output ROOT file') -parser.add_argument('--plotdir', type=str, help='Directory to dump plots', - default='plots') +parser.add_argument('--plotdir', type=str, help='Directory to dump plots', default='plots') parser.add_argument('--debug', action='store_true', help='Be verbose in output') parser.add_argument('--mode', type=str, help='Zee or Zmumu') - - args = parser.parse_args() infilename = args.infile -infile = ROOT.TFile.Open(infilename, 'READ') +runmode = args.mode +infile = ROOT.TFile.Open(infilename, 'READ') + + +def trigTP(h, effcyt): + yld = (h[2], h[3]) + ylderr = (h.GetBinError(2), h.GetBinError(3)) + A, B = yld + o_z_one[0], o_z_two[0] = yld + + if B == 0: + return + + eff = 1./(float(A)/B/2.+1.) + inverrsq = ((1/2./B)*ylderr[0])**2+((A/2./B**2)*ylderr[1])**2 + o_trigeff[0] = eff + o_trigeffstat[0] = (inverrsq**.5)*(eff**2) + o_run[0], o_lb[0] = int(runname[4:]), lbnum + try: + iov = lblb[int(runname[4:])][lbnum-1] + o_lbwhen[0], o_lbwhen[1] = iov.StartTime/1e9, iov.EndTime/1e9 + except Exception, e: + o_lbwhen[0], o_lbwhen[1] = 0, 0 + + effcyt.SetBinContent(lbnum-lbnums[0]+1, eff) + effcyt.SetBinError(lbnum-lbnums[0]+1, o_trigeffstat[0]) + + +def recoTP(hmo, hms, hno, hns, effcyr): + bin1 = hmo.GetXaxis().FindBin(86000) + bin2 = hmo.GetXaxis().FindBin(95000) + matchos, matchoserr = extract(hmo, bin1, bin2) + matchss, matchsserr = extract(hms, bin1, bin2) + nomatchos, nomatchoserr = extract(hno, bin1, bin2) + nomatchss, nomatchsserr = extract(hns, bin1, bin2) + + A = float(matchos-matchss) + Aerr = (matchoserr**2+matchsserr**2)**.5 + B = float(nomatchos-nomatchss) + Berr = (nomatchoserr**2+nomatchsserr**2)**.5 + + if Berr == 0: + Berr = 1. + if A == 0 or B/A == -1: + eff = 1. + inverrsq = 1. + else: + eff = 1./(1.+B/A) + inverrsq = ((-B/A**2)*Aerr)**2+((1./A)*Berr)**2 + + o_recoeff[0] = eff + o_recoeffstat[0] = (inverrsq**.5)*(eff**2) + effcyr.SetBinContent(lbnum-lbnums[0]+1, eff) + effcyr.SetBinError(lbnum-lbnums[0]+1, o_recoeffstat[0]) + + +def templateMethod(hmo, hms, hno, hns, hto, hts, effcyr): + noSign = False + doScale = False + + tbin1 = hmo.GetXaxis().FindBin(75000) + tbin2 = hmo.GetXaxis().FindBin(104000) + tbin3 = hmo.GetXaxis().FindBin(120000) + tbin4 = hmo.GetXaxis().FindBin(250000) + + scale_os = 1 if hto.Integral(tbin3, tbin4) == 0 else hno.Integral(tbin3, tbin4)/hto.Integral(tbin3, tbin4) + scale_ss = 1 if hts.Integral(tbin3, tbin4) == 0 else hns.Integral(tbin3, tbin4)/hts.Integral(tbin3, tbin4) + + if doScale == True: + hto.Scale(scale_os) + hts.Scale(scale_ss) + + if noSign == True: + hmo.Add(hms) + hno.Add(hns) + hto.Add(hts) + + matchos_peak, matchos_peakerr = extract(hmo, tbin1, tbin2) + matchos_tail, matchos_tailerr = extract(hmo, tbin3, tbin4) + matchss_peak, matchss_peakerr = extract(hms, tbin1, tbin2) + matchss_tail, matchss_tailerr = extract(hms, tbin3, tbin4) + + nomatchos_peak, nomatchos_peakerr = extract(hno, tbin1, tbin2) + nomatchos_tail, nomatchos_tailerr = extract(hno, tbin3, tbin4) + nomatchss_peak, nomatchss_peakerr = extract(hns, tbin1, tbin2) + nomatchss_tail, nomatchss_tailerr = extract(hns, tbin3, tbin4) + + templateos_peak, templateos_peakerr = extract(hto, tbin1, tbin2) + templateos_tail, templateos_tailerr = extract(hto, tbin3, tbin4) + templatess_peak, templatess_peakerr = extract(hts, tbin1, tbin2) + templatess_tail, templatess_tailerr = extract(hts, tbin3, tbin4) + + totalos_peak = matchos_peak + nomatchos_peak + totalos_tail = matchos_tail + nomatchos_tail + totalss_peak = matchss_peak + nomatchss_peak + totalss_tail = matchss_tail + nomatchss_tail + + totalos_peakerr = pow(totalos_peak, 0.5) + totalss_peakerr = pow(totalss_peak, 0.5) + totalos_tailerr = pow(totalos_tail, 0.5) + totalss_tailerr = pow(totalss_tail, 0.5) + + if templatess_tail == 0: + eff = 1 + err = 1 + elif templateos_tail == 0: + eff = 1 + err = 1 + + if templatess_tail != 0 and templateos_tail != 0: + n1 = matchos_peak + n2 = (templateos_peak*matchss_tail)/templatess_tail + d1 = totalos_peak + d2 = (nomatchos_tail*templateos_peak)/templateos_tail + + eff = (n1 - n2)/(d1- d2) + err = templateTPErr(hmo, hms, hno, hns, hto, hts) + + + o_recoeff[0] = eff + o_recoeffstat[0] = err + effcyr.SetBinContent(lbnum-lbnums[0]+1, eff) + effcyr.SetBinError(lbnum-lbnums[0]+1, err) + + +def templateTPErr(hmo, hms, hno, hns, hto, hts): + bin1 = hmo.GetXaxis().FindBin(75000) + bin2 = hmo.GetXaxis().FindBin(104000) + bin3 = hmo.GetXaxis().FindBin(120000) + bin4 = hmo.GetXaxis().FindBin(250000) + + a, da = extract(hmo, bin1, bin2) + b, db = extract(hms, bin3, bin4) + c, dc = extract(hto, bin1, bin2) + d, dd = extract(hts, bin3, bin4) + e, de = extract(hno, bin1, bin2) + f, df = extract(hno, bin3, bin4) + g, dg = extract(hto, bin3, bin4) + + try: + dva = 1/(a-(c*f)/g+e)-(a-(b*c)/d)/(a-(c*f)/g+e)**2 + except ZeroDivisionError: + return 1 + try: + dvb = -c/(d*(-(c*f)/g+a+e)) + except ZeroDivisionError: + return 1 + try: + dvc = -(g*((a+e)*b*g-a*d*f))/(d*(f*c+(-a-e)*g)**2) + except ZeroDivisionError: + return 1 + try: + dvd = (b*c)/((-(c*f)/g+a+e)*d**2) + except ZeroDivisionError: + return 1 + try: + dve = -(a-(b*c)/d)/(e-(c*f)/g+a)**2 + except ZeroDivisionError: + return 1 + try: + dvf = (c*(a-(b*c)/d))/(g*(-(c*f)/g+a+e)**2) + except ZeroDivisionError: + return 1 + try: + dvg = -(c*(a*d-b*c)*f)/(d*((a+e)*g-c*f)**2) + except ZeroDivisionError: + return 1 + + verbose = False + if verbose == True: + print a, da, dva, da*dva + print b, db, dvb, db*dvb + print c, dc, dvc, dc*dvc + print d, dd, dvd, dd*dvd + print e, de, dve, de*dve + print f, df, dvf, df*dvf + print g, dg, dvg, dg*dvg + + err = math.sqrt((da*dva)**2 + (db*dvb)**2 + (dc*dvc)**2 + (dd*dvd)**2 + (de*dve)**2 + (df*dvf)**2 + (dg*dvg)**2) + return err + +def containerEff(h_photon, h_pass, h_tos, h_tss): + h_temp = h_tos.Clone() + h_temp.Add(h_tss) + + bin1 = h_pass.FindBin(120000) + bin2 = h_pass.FindBin(250000) + scale = h_pass.Integral(bin1, bin2)/h_temp.Integral(bin1, bin2) + h_temp.Scale(scale) + + scale_err = scale*pow((1/math.sqrt(h_pass.Integral(bin1, bin2)))+(1/math.sqrt(h_temp.Integral(bin1, bin2))), 0.5) + + bin66 = h_photon.FindBin(66000) + bin75 = h_photon.FindBin(75000) + bin100 = h_photon.FindBin(100000) + bin116 = h_photon.FindBin(116000) + + N6675 = h_photon.Integral(bin66, bin75) + N100116 = h_photon.Integral(bin100, bin116) + sigW = 96 - 86 + bkgW = (75 - 66) + (116 - 100) + + bkg = (N6675+N100116)*sigW/bkgW + bkgerr = pow(N6675 + N100116, 0.5)*sigW/bkgW + + bin86 = h_pass.FindBin(86000) + bin96 = h_pass.FindBin(96000) + + passval = h_pass.Integral(bin86, bin96) - h_temp.Integral(bin86, bin96) + passerr = pow(h_pass.Integral(bin86, bin96) + math.sqrt(scale)*h_temp.Integral(bin86, bin96) + scale_err**2, 0.5) + + photonval = h_photon.Integral(bin86, bin96) + photonerr = pow(h_photon.Integral(bin86, bin96), 0.5) + + a = passval + b = photonval + c = bkg + da = passerr + db = photonerr + dc = bkgerr + + dda = (b-c)/(b-c+a)**2 + ddb = -a/(b-c+a)**2 + ddc = a/(b-c+a)**2 + + o_conteff[0] = passval/(photonval - bkg + passval) + o_conteffstat[0] = math.sqrt((da*dda)**2 + (db*ddb)**2 + (dc*ddc)**2) + + +def extract(histogram, bin1, bin2): + dbl = ROOT.Double() + rv1 = histogram.IntegralAndError(bin1, bin2, dbl) + return (rv1, float(dbl)) + -runmode = args.mode print 'Running in', runmode, 'mode' +if runmode == "Zmumu": + ACCEPTANCE = 0.3323224 +if runmode == "Zee": + ACCEPTANCE = 0.2996 runname = None @@ -46,30 +279,28 @@ for k in infile.Get(runname).GetListOfKeys(): print 'Now to dump' lbnums = sorted([int(_[3:]) for _ in lbdirs]) -effcyt = ROOT.TH1F('effcyt', 'Trigger efficiency', lbnums[-1]-lbnums[0]+1, lbnums[0]-0.5, - lbnums[-1]+0.5) -effcyr = ROOT.TH1F('effcyr', 'Loose muon reco efficiency', lbnums[-1]-lbnums[0]+1, lbnums[0]-0.5, - lbnums[-1]+0.5) -effcya = ROOT.TH1F('effcya', 'Combined acc x efficiency', lbnums[-1]-lbnums[0]+1, lbnums[0]-0.5, - lbnums[-1]+0.5) -effcydir = ROOT.TH1F('effcydir', 'Direct acc x efficiency', lbnums[-1]-lbnums[0]+1, lbnums[0]-0.5, - lbnums[-1]+0.5) +effcyt = ROOT.TH1F('effcyt', 'Trigger efficiency', lbnums[-1]-lbnums[0]+1, lbnums[0]-0.5, lbnums[-1]+0.5) +effcyr = ROOT.TH1F('effcyr', 'Loose electron reco efficiency', lbnums[-1]-lbnums[0]+1, lbnums[0]-0.5, lbnums[-1]+0.5) +effcya = ROOT.TH1F('effcya', 'Combined acc x efficiency', lbnums[-1]-lbnums[0]+1, lbnums[0]-0.5, lbnums[-1]+0.5) +effcydir = ROOT.TH1F('effcydir', 'Direct acc x efficiency', lbnums[-1]-lbnums[0]+1, lbnums[0]-0.5, lbnums[-1]+0.5) -from array import array fout = ROOT.TFile(args.out if args.out else '%s_all.root' % runname[4:], 'RECREATE') -o_run = array('I', [0]) -o_lb = array('I', [0]) -o_lbwhen = array('d', [0., 0.]) -o_z_one = array('f', [0.]) -o_z_two = array('f', [0.]) -o_trigeff = array('f', [0.]) -o_trigeffstat = array('f', [0.]) -o_recoeff = array('f', [0.]) -o_recoeffstat = array('f', [0.]) -o_alleff = array('f', [0.]) -o_alleffstat = array('f', [0.]) -o_ae = array('f', [0.]) -o_aestat = array('f', [0.]) +o_run = array('I', [0]) +o_lb = array('I', [0]) +o_lbwhen = array('d', [0., 0.]) +o_z_one = array('f', [0.]) +o_z_two = array('f', [0.]) +o_trigeff = array('f', [0.]) +o_trigeffstat = array('f', [0.]) +o_recoeff = array('f', [0.]) +o_recoeffstat = array('f', [0.]) +o_conteff = array('f', [0.]) +o_conteffstat = array('f', [0.]) +o_alleff = array('f', [0.]) +o_alleffstat = array('f', [0.]) +o_ae = array('f', [0.]) +o_aestat = array('f', [0.]) + tl = ROOT.TTree( 'lumitree', 'Luminosity tree' ) tl.Branch('run', o_run, 'run/i') tl.Branch('lb', o_lb, 'lb/i') @@ -80,83 +311,47 @@ tl.Branch('trigeff', o_trigeff, 'trigeff/F') tl.Branch('trigeffstat', o_trigeffstat, 'trigeffstat/F') tl.Branch('recoeff', o_recoeff, 'recoeff/F') tl.Branch('recoeffstat', o_recoeffstat, 'recoeffstat/F') +tl.Branch('conteff', o_conteff, 'conteff/F') +tl.Branch('conteffstat', o_conteffstat, 'conteffstat/F') tl.Branch('alleff', o_alleff, 'alleff/F') tl.Branch('alleffstat', o_alleffstat, 'alleffstat/F') tl.Branch('ae', o_ae, 'ae/F') tl.Branch('aestat', o_aestat, 'aestat/F') -from DQUtils import fetch_iovs -#rset=set(_[0] for _ in rlb) -#print rset lblb = fetch_iovs("LBLB", runs=int(runname[4:])).by_run for lb in sorted(lbdirs): if runmode == "Zee": - h = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_eltrigtp_matches' % (runname, lb)) + h = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_eltrigtp_matches_os' % (runname, lb)) hmo = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_os' % (runname, lb)) hms = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_good_ss' % (runname, lb)) hno = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_os' % (runname, lb)) hns = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_bad_ss' % (runname, lb)) + hto = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_template_os' % (runname, lb)) + hts = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_template_ss' % (runname, lb)) + hphoton = infile.Get("%s/%s/GLOBAL/DQTGlobalWZFinder/m_elContainertp_nomatch" % (runname, lb)) + hpass = infile.Get("%s/%s/GLOBAL/DQTGlobalWZFinder/m_ele_tight_passkine" % (runname, lb)) + if runmode == "Zmumu": h = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_mutrigtp_matches' % (runname, lb)) hmo = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_match_os' % (runname, lb)) hms = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_match_ss' % (runname, lb)) hno = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_nomatch_os' % (runname, lb)) hns = infile.Get('%s/%s/GLOBAL/DQTGlobalWZFinder/m_muloosetp_nomatch_ss' % (runname, lb)) - lbnum = int(lb[3:]) - yld = (h[2], h[3]) - ylderr = (h.GetBinError(2), h.GetBinError(3)) - #print yld, ylderr - A, B = yld - o_z_one[0], o_z_two[0] = yld - if B == 0: continue - eff = 1./(float(A)/B/2.+1.) - inverrsq = ((1/2./B)*ylderr[0])**2+((A/2./B**2)*ylderr[1])**2 - o_trigeff[0] = eff - o_trigeffstat[0] = (inverrsq**.5)*(eff**2) - o_run[0], o_lb[0] = int(runname[4:]), lbnum - try: - iov = lblb[int(runname[4:])][lbnum-1] - o_lbwhen[0], o_lbwhen[1] = iov.StartTime/1e9, iov.EndTime/1e9 - except Exception, e: - o_lbwhen[0], o_lbwhen[1] = 0, 0 - effcyt.SetBinContent(lbnum-lbnums[0]+1, eff) - effcyt.SetBinError(lbnum-lbnums[0]+1, o_trigeffstat[0]) - def extract(histogram): - dbl = ROOT.Double() - rv1 = histogram.IntegralAndError(21, 30, dbl) - return (rv1, float(dbl)) - matchos, matchoserr = extract(hmo) - matchss, matchsserr = extract(hms) - nomatchos, nomatchoserr = extract(hno) - nomatchss, nomatchsserr = extract(hns) - if args.debug: - print lb - print ' ->', matchos, matchoserr - print ' ->', matchss, matchsserr - print ' ->', nomatchos, nomatchoserr - print ' ->', nomatchss, nomatchsserr - A = float(matchos-matchss) - Aerr = (matchoserr**2+matchsserr**2)**.5 - B = float(nomatchos-nomatchss) - Berr = (nomatchoserr**2+nomatchsserr**2)**.5 - if Berr == 0: Berr = 1. - if A == 0 or B/A == -1: - eff = 1. - inverrsq = 1. - else: - eff = 1./(1.+B/A) - inverrsq = ((-B/A**2)*Aerr)**2+((1./A)*Berr)**2 - o_recoeff[0] = eff - o_recoeffstat[0] = (inverrsq**.5)*(eff**2) - effcyr.SetBinContent(lbnum-lbnums[0]+1, eff) - effcyr.SetBinError(lbnum-lbnums[0]+1, o_recoeffstat[0]) + lbnum = int(lb[3:]) + trigTP(h, effcyt) + if runmode == "Zmumu": + recoTP(hmo, hms, hno, hns, effcyr) + elif runmode == "Zee": + templateMethod(hmo, hms, hno, hns, hto, hts, effcyr) + containerEff(hphoton, hpass, hto, hts) - o_ae[0] = ACCEPTANCE*(1-(1-o_trigeff[0])**2)*(o_recoeff[0])**2 - o_aestat[0] = ACCEPTANCE*((o_recoeff[0]**2*2*(1-o_trigeff[0])*o_trigeffstat[0])**2+(2*o_recoeff[0]*(1-(1-o_trigeff[0])**2)*o_recoeffstat[0])**2)**.5 - o_alleff[0] = (1-(1-o_trigeff[0])**2)*(o_recoeff[0])**2 + o_ae[0] = ACCEPTANCE*(1-(1-o_trigeff[0])**2)*(o_recoeff[0])**2 + o_aestat[0] = ACCEPTANCE*((o_recoeff[0]**2*2*(1-o_trigeff[0])*o_trigeffstat[0])**2+(2*o_recoeff[0]*(1-(1-o_trigeff[0])**2)*o_recoeffstat[0])**2)**.5 + o_alleff[0] = (1-(1-o_trigeff[0])**2)*(o_recoeff[0])**2 o_alleffstat[0] = ((o_recoeff[0]**2*2*(1-o_trigeff[0])*o_trigeffstat[0])**2+(2*o_recoeff[0]*(1-(1-o_trigeff[0])**2)*o_recoeffstat[0])**2)**.5 + effcya.SetBinContent(lbnum-lbnums[0]+1, o_ae[0]) effcya.SetBinError(lbnum-lbnums[0]+1, o_aestat[0]) @@ -168,22 +363,24 @@ print 'Done' c1 = ROOT.TCanvas() effcya.SetMarkerStyle(21) effcya.SetMarkerColor(ROOT.kBlue) -effcya.GetYaxis().SetRangeUser(0.25,0.31) +effcya.GetYaxis().SetRangeUser(0, 0.4) effcya.Draw('PE') c1.Print(os.path.join(args.plotdir, '%s_combined_efficiency.eps' % runname[4:])) fout.WriteTObject(effcya) c1.Clear() effcyt.SetMarkerStyle(21) effcyt.SetMarkerColor(ROOT.kBlue) -effcyt.GetYaxis().SetRangeUser(0.66,0.86) +effcyt.GetYaxis().SetRangeUser(0.6,1.0) effcyt.Draw('PE') +effcyt.Fit('pol1') c1.Print(os.path.join(args.plotdir, '%s_trigger_efficiency.eps' % runname[4:])) fout.WriteTObject(effcyt) c1.Clear() effcyr.SetMarkerStyle(21) effcyr.SetMarkerColor(ROOT.kBlue) -effcyr.GetYaxis().SetRangeUser(0.9,1.0) +effcyr.GetYaxis().SetRangeUser(0.7,1.0) effcyr.Draw('PE') +effcyr.Fit('pol1') c1.Print(os.path.join(args.plotdir, '%s_reco_efficiency.eps' % runname[4:])) fout.WriteTObject(effcyr) fout.Close() @@ -198,7 +395,6 @@ if sumweights: for ibin in xrange(1,sumweights.GetNbinsX()+1): o_lb[0] = int(sumweights.GetBinCenter(ibin)) ctrbin = ctr.FindBin(o_lb[0]) - print ibin, o_lb[0], sumweights[ibin], ctr[ctrbin] if sumweights[ibin] == 0: continue p = ctr[ctrbin]/sumweights[ibin] o_alleff[0]=p @@ -209,7 +405,7 @@ if sumweights: effcydir.SetBinContent(effcydir.FindBin(o_lb[0]), p) effcydir.SetBinError(effcydir.FindBin(o_lb[0]), o_alleffstat[0]) - effcya.GetYaxis().SetRangeUser(0.27,0.31) + effcya.GetYaxis().SetRangeUser(0.00,0.50) effcya.Draw('PE') effcydir.SetMarkerStyle(20) effcydir.SetMarkerColor(ROOT.kRed) @@ -227,3 +423,8 @@ if sumweights: effcyrat.Draw('PE') effcyrat.Fit('pol1') c1.Print(os.path.join(args.plotdir, '%s_tp_correction.eps' % runname[4:])) + + + + + diff --git a/DataQuality/ZLumiScripts/scripts/dqt_zlumi_combine_lumi.py b/DataQuality/ZLumiScripts/scripts/dqt_zlumi_combine_lumi.py index 9cefac39d98184e18c11aab1d3bb55dac8afad58..e9c800383eaf11c67b58520ef6e013cd545e6bd7 100755 --- a/DataQuality/ZLumiScripts/scripts/dqt_zlumi_combine_lumi.py +++ b/DataQuality/ZLumiScripts/scripts/dqt_zlumi_combine_lumi.py @@ -2,40 +2,64 @@ # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration import ROOT import sys - import argparse +from array import array + +ROOT.gROOT.SetBatch(ROOT.kTRUE) + + parser = argparse.ArgumentParser() parser.add_argument('recofile', type=str, help='File with per-LB yields') parser.add_argument('efffile', type=str, help='File with efficiencies') parser.add_argument('outfile', type=str, help='Output file') -parser.add_argument('--nlb', type=int, help='# of LBs to combine', - default=20) -args = parser.parse_args() +parser.add_argument('--nlb', type=int, help='# of LBs to combine', default=20) +parser.add_argument('--mode', type=str, help='Zee or Zmumu') +parser.add_argument('--campaign', type=str, help='MC campaign corresponding to year of run') + +args = parser.parse_args() +runmode = args.mode +campaign = args.campaign +recozfname = args.recofile +effzfname = args.efffile +outfname = args.outfile +LUMIBLOCKS = args.nlb -recozfname = args.recofile -effzfname = args.efffile -outfname = args.outfile +ZXSEC = 1.929 +ZPURITYFACTOR = 0.9935 + +if runmode == "Zmumu": + ACCEPTANCE = 0.3323224 +if runmode == "Zee": + ACCEPTANCE = 0.2996 -LUMIBLOCKS = args.nlb -#ACCEPTANCE = 3.173927e-01 -ACCEPTANCE = 3.323224e-01 -ZXSEC=1.929 -ZPURITYFACTOR=0.9935 def correction(mu): - # R20.7 - # return 1.04524-0.000108956*mu - # R21 - #return 1.04701-0.000206159*mu - return 0.998758-0.000157214*mu - #return 1. + if runmode == "Zee": + if campaign == "mc16a": + return 8.83702e-01 - 5.04610e-04*mu - 3.96025e-06*mu*mu + if campaign == "mc16d": + return 8.74735e-01 - 1.64286e-04*mu - 7.32040e-06*mu*mu + if campaign == "mc16e": + # old method + #return 8.74217e-01 - 1.66188e-04*mu - 7.75133e-06*mu*mu + # template method - OS = OS+SS + #return 9.32014e-01 + 1.49928e-06*mu - 5.28293e-06*mu*mu + # template method - OS = OS + return 9.02495e-01 + 2.15661e-05*mu - 7.04916e-06*mu*mu -recozfile = ROOT.TFile.Open(recozfname) -effzfile = ROOT.TFile.Open(effzfname) + if runmode == "Zmumu": + if campaign == "mc16a": + return 9.90074e-01 - 5.34716e-06*mu - 3.23366e-06*mu*mu + if campaign == "mc16d": + return 9.91619e-01 - 1.21674e-04*mu - 1.58362e-06*mu*mu + if campaign == "mc16e": + return 9.90808e-01 - 9.99749e-05*mu - 1.40241e-06*mu*mu -recoztree = recozfile.lumitree -effztree = effzfile.lumitree +recozfile = ROOT.TFile.Open(recozfname) +effzfile = ROOT.TFile.Open(effzfname) +recoztree = recozfile.lumitree +effztree = effzfile.lumitree entrydict = {} for i in xrange(recoztree.GetEntries()): @@ -50,7 +74,8 @@ for i in xrange(recoztree.GetEntries()): continue lbzero = (recoztree.lb // LUMIBLOCKS)*LUMIBLOCKS run = recoztree.run - if (run, lbzero) not in entrydict: entrydict[(run, lbzero)] = {'zcount': 0., 'zcounterrsq': 0., 'livetime': 0., 'lbwhen': [-1, -1], 'mu': 0., 'offlumi': 0., 'rolleff': 0., 'rollefferrsq': 0., 'lhcfill': recoztree.lhcfill} + if (run, lbzero) not in entrydict: + entrydict[(run, lbzero)] = {'zcount': 0., 'zcounterrsq': 0., 'livetime': 0., 'lbwhen': [-1, -1], 'mu': 0., 'offlumi': 0., 'rolleff': 0., 'rollefferrsq': 0., 'lhcfill': recoztree.lhcfill} thisdict = entrydict[(run, lbzero)] effcy = (effztree.GetV1()[0]*correction(recoztree.mu)) #thisdict['zcount'] += recoztree.zraw/effcy @@ -70,22 +95,22 @@ for i in xrange(recoztree.GetEntries()): if thisdict['lbwhen'][1] < recoztree.lbwhen[1] or thisdict['lbwhen'][1] == -1: thisdict['lbwhen'][1] = recoztree.lbwhen[1] -from array import array fout = ROOT.TFile.Open(outfname, 'RECREATE') -o_run = array('I', [0]) -o_lb = array('I', [0]) -o_lbwhen = array('d', [0., 0.]) -o_zrate = array('f', [0.]) -o_zratestat = array('f', [0.]) -o_zlumi = array('f', [0.]) -o_zlumistat = array('f', [0.]) -o_mu = array('f', [0.]) -o_alleffcorr = array('f', [0.]) +o_run = array('I', [0]) +o_lb = array('I', [0]) +o_lbwhen = array('d', [0., 0.]) +o_zrate = array('f', [0.]) +o_zratestat = array('f', [0.]) +o_zlumi = array('f', [0.]) +o_zlumistat = array('f', [0.]) +o_mu = array('f', [0.]) +o_alleffcorr = array('f', [0.]) o_alleffcorrstat = array('f', [0.]) -o_offlumi = array('f', [0.]) -o_lblive = array('f', [0.]) -o_lhcfill = array('I', [0]) +o_offlumi = array('f', [0.]) +o_lblive = array('f', [0.]) +o_lhcfill = array('I', [0]) + t = ROOT.TTree( 'lumitree', 'Luminosity tree' ) t.Branch('run', o_run, 'run/i') t.Branch('lb', o_lb, 'lb/i') @@ -107,9 +132,8 @@ for entry, entryval in sorted(entrydict.items()): entryval['offlumi'] /= entryval['livetime'] eff = entryval['rolleff']/entryval['rollefferrsq'] efferr = 1/entryval['rollefferrsq']**.5 - #print 'LIVETIME2', entryval['livetime'] entryval['zrate'] = entryval['zcount']/eff/entryval['livetime'] - entryval['zratestat'] = (entryval['zcounterrsq']/eff/eff + (entryval['zcount']/eff**2*efferr)**2)**.5/entryval['livetime'] + entryval['zratestat'] = (entryval['zcounterrsq']/eff + (entryval['zcount']/eff**2*efferr)**2)**.5/entryval['livetime'] o_run[0], o_lb[0] = entry o_lbwhen[0], o_lbwhen[1] = entryval['lbwhen'] o_zrate[0] = entryval['zrate'] @@ -122,9 +146,9 @@ for entry, entryval in sorted(entrydict.items()): o_offlumi[0] = entryval['offlumi'] o_lblive[0] = entryval['livetime'] o_lhcfill[0] = entryval['lhcfill'] - if o_zlumi[0] < 4 or o_zlumi[0] > 15: - print o_lb[0], o_zlumi[0], entryval['zcount'], eff, entryval['livetime'] + t.Fill() + #t.Write() newrzt = recoztree.CloneTree() newrzt.SetName("recolumitree") diff --git a/DataQuality/ZLumiScripts/scripts/dqt_zlumi_compute_lumi.py b/DataQuality/ZLumiScripts/scripts/dqt_zlumi_compute_lumi.py index 44a2e9f770cd55b203052f4fd1ba02776233db5a..82be430b92bf4c7ba63d387747b6717a813e442f 100755 --- a/DataQuality/ZLumiScripts/scripts/dqt_zlumi_compute_lumi.py +++ b/DataQuality/ZLumiScripts/scripts/dqt_zlumi_compute_lumi.py @@ -2,6 +2,7 @@ # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration import ROOT +ROOT.gROOT.SetBatch(ROOT.kTRUE) import sys, os import logging logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO) @@ -26,10 +27,8 @@ parser.add_argument('--mode', type=str, help='Zee or Zmumu') args = parser.parse_args() BINWIDTH=10 - ZPURITYFACTOR=0.9935 ZXSEC=1.929 -#ZATIMESC=0.2578 ZATIMESC=0.29632 def mu_dep_eff(mu): @@ -51,8 +50,9 @@ for key in fin.GetListOfKeys(): break if args.grl: - import DQUtils - grl = DQUtils.grl.load_grl(args.grl) + grlReader = ROOT.Root.TGoodRunsListReader(args.grl) + grlReader.Interpret() + grl = grlReader.GetMergedGRLCollection() else: grl = None @@ -60,18 +60,12 @@ if not runname: logging.critical("Can't find run_* directory in input file %s", args.infile) sys.exit(1) -z_m = fin.Get('%s/GLOBAL/DQTGlobalWZFinder/m_Z_Counter_mu' % runname) -if args.out: - outfname = args.out -else: - outfname = '%s_data.root' % runname[4:] - runmode = args.mode print 'Running in', runmode, 'mode' if runmode == 'Zee': - z_m = fin.Get('%s/GLOBAL/DQTGlobalWZFinder/m_Z_Counter_el' % runname) + z_m = fin.Get('%s/GLOBAL/DQTGlobalWZFinder/m_Z_Counter_el_os' % runname) if not z_m: - logging.critical("Can't retrieve m_Z_Counter_el") + logging.critical("Can't retrieve m_Z_Counter_el_os") sys.exit(1) if runmode == 'Zmumu': @@ -80,6 +74,10 @@ if runmode == 'Zmumu': logging.critical("Can't retrieve m_Z_Counter_mu") sys.exit(1) +if args.out: + outfname = args.out +else: + outfname = '%s_data.root' % runname[4:] fout = None t = None @@ -198,20 +196,13 @@ if runmode == 'Zmumu': efftitle = 'eff #sigma, Z->#mu#mu' lumirawtitle = 'Lumi, Z->#mu#mu per LB' - -lumiplot_m = ROOT.TH1F('lumiplot_m', lumititle % runname[4:], - int(nrebinned_bins), - lbmin, lbmin+BINWIDTH*nrebinned_bins) -lumiplot_m_ratio = ROOT.TH1F('lumiplot_m_ratio', 'Z/official lumi ratio (Run %s)' % runname[4:], - int(nrebinned_bins), - lbmin, lbmin+BINWIDTH*nrebinned_bins) +lumiplot_m = ROOT.TH1F('lumiplot_m', lumititle, int(nrebinned_bins), lbmin, lbmin+BINWIDTH*nrebinned_bins) +lumiplot_m_ratio = ROOT.TH1F('lumiplot_m_ratio', 'Z/official lumi ratio (Run %s)' % runname[4:], int(nrebinned_bins), lbmin, lbmin+BINWIDTH*nrebinned_bins) lumiplot_m.SetXTitle('LB') lumiplot_m.SetYTitle('Luminosity (x 10^{33} cm^{-2} s^{-1})') -xsec_m = ROOT.TH1F('xsec_m', efftitle, int(nrebinned_bins), - lbmin, lbmin+BINWIDTH*nrebinned_bins) -lumiplot_raw_m = ROOT.TH1F('lumiplot_raw_m', lumirawtitle, - int(lbmax-lbmin), - lbmin, lbmax) + +xsec_m = ROOT.TH1F('xsec_m', efftitle, int(nrebinned_bins), lbmin, lbmin+BINWIDTH*nrebinned_bins) +lumiplot_raw_m = ROOT.TH1F('lumiplot_raw_m', lumirawtitle, int(lbmax-lbmin), lbmin, lbmax) num_m, lum, denom, weighted_mu = 0, 0, 0, 0 tot_num_m, tot_denom, tot_lum = 0, 0, 0 @@ -226,7 +217,7 @@ for ibin in xrange(1, int(lbmax-lbmin)+1): l_zatimesc = mu_dep_eff(official_mu[ibin]) else: l_zatimesc = ZATIMESC - if grl and not DQUtils.grl.grl_contains_run_lb(grl, (int(runname[4:]), int(lumiplot_raw_m.GetBinCenter(ibin)))): + if grl and not grl.HasRunLumiBlock(int(runname[4:]), int(lumiplot_raw_m.GetBinCenter(ibin))): o_passgrl[0]=0 else: o_passgrl[0]=1 diff --git a/DataQuality/ZLumiScripts/scripts/dqt_zlumi_display_z_rate.py b/DataQuality/ZLumiScripts/scripts/dqt_zlumi_display_z_rate.py index ca5211c06ebd044fa9a31fc440533a053d4355ef..b0b2c4dc0245cf8eb78f08ca7d85fde3a29a2d18 100755 --- a/DataQuality/ZLumiScripts/scripts/dqt_zlumi_display_z_rate.py +++ b/DataQuality/ZLumiScripts/scripts/dqt_zlumi_display_z_rate.py @@ -6,6 +6,7 @@ import sys, os import array import argparse import time +ROOT.gROOT.SetBatch(ROOT.kTRUE) parser = argparse.ArgumentParser() parser.add_argument('infile', type=str, help='input HIST file') diff --git a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/versions/CaloCluster_v1.h b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/versions/CaloCluster_v1.h index fd20d4e8a9ecf2f0f4fb44ea5ca0a6f5b136ef63..5d1bf70ea4636ce1b28529a8fb82e49b7a6bd33b 100644 --- a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/versions/CaloCluster_v1.h +++ b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/versions/CaloCluster_v1.h @@ -80,14 +80,12 @@ namespace xAOD { Topo_633 = 12, // transient cluster for AODCellContainer SW_7_11 = 13, - // cluster representation of towers - Tower_01_01 = 14, - Tower_005_005 = 15, - - - //New (2016) egamma cluster SuperCluster=14, + //New (2019) cluster representation of towers + Tower_01_01 = 15, + Tower_005_005 = 16, + Tower_fixed_area = 17, CSize_Unknown = 99 }; diff --git a/Event/xAOD/xAODCnvInterfaces/xAODCnvInterfaces/IEventInfoCnvTool.h b/Event/xAOD/xAODCnvInterfaces/xAODCnvInterfaces/IEventInfoCnvTool.h index c0a33d117f28b3fd7581b840ac5e569661852119..919522a7dcef4fc0df55a4dcf572bd7755915887 100644 --- a/Event/xAOD/xAODCnvInterfaces/xAODCnvInterfaces/IEventInfoCnvTool.h +++ b/Event/xAOD/xAODCnvInterfaces/xAODCnvInterfaces/IEventInfoCnvTool.h @@ -43,7 +43,8 @@ namespace xAODMaker { virtual StatusCode convert( const EventInfo* aod, xAOD::EventInfo* xaod, bool pileUpInfo = false, - bool copyPileUpLinks = true ) = 0; + bool copyPileUpLinks = true, + bool forceMCInfoCopy = false) = 0; /// Gaudi interface definition static const InterfaceID& interfaceID() { diff --git a/Event/xAOD/xAODEventInfoCnv/src/EventInfoCnvTool.cxx b/Event/xAOD/xAODEventInfoCnv/src/EventInfoCnvTool.cxx index 400c3c8c58985b2b249278c779049165ee4a8ff5..1dc82341a959b2d73a6fe9ed19fc3df83c9534d6 100644 --- a/Event/xAOD/xAODEventInfoCnv/src/EventInfoCnvTool.cxx +++ b/Event/xAOD/xAODEventInfoCnv/src/EventInfoCnvTool.cxx @@ -113,7 +113,8 @@ namespace xAODMaker { StatusCode EventInfoCnvTool::convert( const EventInfo* aod, xAOD::EventInfo* xaod, bool pileUpInfo, - bool copyPileUpLinks ) { + bool copyPileUpLinks, + bool forceMCInfoCopy) { if( ! aod ) { ATH_MSG_WARNING( "Null pointer received for input!" ); @@ -150,8 +151,9 @@ namespace xAODMaker { eventTypeBitmask |= xAOD::EventInfo::IS_CALIBRATION; } xaod->setEventTypeBitmask( eventTypeBitmask ); - // Only add MC information for simulation files: - if( xaod->eventType( xAOD::EventInfo::IS_SIMULATION ) ) { + // Only add MC information for simulation files + //or for Data+MC overlay + if( xaod->eventType( xAOD::EventInfo::IS_SIMULATION ) || forceMCInfoCopy ) { xaod->setMCChannelNumber( aod->event_type()->mc_channel_number() ); xaod->setMCEventNumber( aod->event_type()->mc_event_number() ); std::vector< float > diff --git a/Event/xAOD/xAODEventInfoCnv/src/EventInfoCnvTool.h b/Event/xAOD/xAODEventInfoCnv/src/EventInfoCnvTool.h index 5d048af20b334d80e2bf8cc3fccebb8d2ff0c979..d0f07160191aacad8b622a63b71ebfa290cae8e8 100644 --- a/Event/xAOD/xAODEventInfoCnv/src/EventInfoCnvTool.h +++ b/Event/xAOD/xAODEventInfoCnv/src/EventInfoCnvTool.h @@ -52,7 +52,8 @@ namespace xAODMaker { virtual StatusCode convert( const EventInfo* aod, xAOD::EventInfo* xaod, bool pileUpInfo = false, - bool copyPileUpLinks = true ); + bool copyPileUpLinks = true, + bool forceMCInfoCopy = false); private: #ifndef XAOD_ANALYSIS diff --git a/InnerDetector/InDetAlignAlgs/InDetAlignGenAlgs/share/CreateMisalignment.py b/InnerDetector/InDetAlignAlgs/InDetAlignGenAlgs/share/CreateMisalignment.py index 7139fd1ac105b3dbd328efb5de7fad84984e8587..ed12bb4688f1fbfdf41cba4e832231e12e19cc99 100644 --- a/InnerDetector/InDetAlignAlgs/InDetAlignGenAlgs/share/CreateMisalignment.py +++ b/InnerDetector/InDetAlignAlgs/InDetAlignGenAlgs/share/CreateMisalignment.py @@ -26,16 +26,15 @@ ROOToutput = True createFreshDB = not(ReadDBPoolFile or MisalignmentOnTopOfExistingSet) if not 'MisalignmentMode' in dir(): - MisalignmentMode = 3 + MisalignmentMode = 11 # Radial -MaximumShift = 200*micrometer +MaximumShift = 100*micrometer if MisalignmentMode in [11, 12,31]: MaximumShift = 500*micrometer -InFile = 'alignment_nominal' -#InFile = 'NominalAlignment' -#InFile = 'MisalignmentSet11' -OutFiles = 'MisalignmentSet%s' % MisalignmentMode +InFile = 'NominalAlignment' +userSuffix = "_p01" +OutFiles = 'MisalignmentSet%s%s' % (MisalignmentMode, userSuffix) ##################################################################### diff --git a/InnerDetector/InDetAlignAlgs/InDetAlignGenAlgs/src/CreateMisalignAlg.cxx b/InnerDetector/InDetAlignAlgs/InDetAlignGenAlgs/src/CreateMisalignAlg.cxx index b137992804ee1f7b199691a15a205ed335d9b51d..bf6a095c0c9b0860f679e635db0c4a853c8a57a2 100644 --- a/InnerDetector/InDetAlignAlgs/InDetAlignGenAlgs/src/CreateMisalignAlg.cxx +++ b/InnerDetector/InDetAlignAlgs/InDetAlignGenAlgs/src/CreateMisalignAlg.cxx @@ -336,12 +336,12 @@ namespace InDetAlignment m_HumanReadableID = m_sctIdHelper->barrel_ec(SCT_ModuleID)*(m_HumanReadableID + 10000000); } - msg(MSG::INFO) << "Human Readable ID: " << m_HumanReadableID << endreq; + msg(MSG::DEBUG) << "-- Human Readable ID: " << m_HumanReadableID << endreq; m_VisualizationLookupTree->Fill(); // Syntax is (ID, Level) where Level is from 1 to 3 (3 is single module level) - if (msgLvl(MSG::INFO)) { + if (msgLvl(MSG::DEBUG)) { HepGeom::Transform3D InitialAlignment = Amg::EigenTransformToCLHEP(m_IDAlignDBTool->getTrans(SCT_ModuleID,3)); msg() << "Initial Alignment of module " << m_idHelper->show_to_string(SCT_ModuleID,0,'/') << endreq; msg() << "Alignment x = (" << InitialAlignment.getTranslation().x() / CLHEP::micrometer << ") micron" << endreq; @@ -389,11 +389,11 @@ namespace InDetAlignment m_HumanReadableID = m_pixelIdHelper->barrel_ec(Pixel_ModuleID)*(m_HumanReadableID + 10000000); } - msg(MSG::INFO) << "Human Readable ID: " << m_HumanReadableID << endreq; + msg(MSG::DEBUG) << "-- Human Readable ID: " << m_HumanReadableID << endreq; m_VisualizationLookupTree->Fill(); - if (msgLvl(MSG::INFO)) { + if (msgLvl(MSG::DEBUG)) { HepGeom::Transform3D InitialAlignment = Amg::EigenTransformToCLHEP(m_IDAlignDBTool->getTrans(Pixel_ModuleID,3)); msg() << "Initial Alignment of module " << m_idHelper->show_to_string(Pixel_ModuleID,0,'/') << endreq; msg() << "Alignment x = (" << InitialAlignment.getTranslation().x() / CLHEP::micrometer << ") micron" << endreq; @@ -583,7 +583,13 @@ namespace InDetAlignment double r = center.rho(); //distance from beampipe double phi = center.phi(); double z = center.z(); - + + msg(MSG::DEBUG) << " Center of the module: radius:"<< r + << " phi: " << phi + << " x: " << r * cos(phi) + << " y: " << r * sin(phi) + << " z: " << z << endreq; + HepGeom::Transform3D parameterizedTrafo; HepGeom::Transform3D alignmentTrafo; @@ -591,7 +597,7 @@ namespace InDetAlignment // prepare scale factor for different subsystems: double ScaleFactor = 1.; - if (m_idHelper->is_pixel(ModuleID)) + if (m_idHelper->is_pixel(ModuleID)) // pixel modules { if (m_pixelIdHelper->is_barrel(ModuleID)) { ScaleFactor=m_ScalePixelBarrel; @@ -605,8 +611,8 @@ namespace InDetAlignment if (m_pixelIdHelper->is_dbm(ModuleID)) { // DBM ScaleFactor=m_ScalePixelDBM; } - - } else if (m_idHelper->is_sct(ModuleID)) + } + else if (m_idHelper->is_sct(ModuleID)) // sct modules { if (m_sctIdHelper->is_barrel(ModuleID)) { ScaleFactor=m_ScaleSCTBarrel; @@ -614,8 +620,9 @@ namespace InDetAlignment else { ScaleFactor=m_ScaleSCTEndcap; } - - } else if (m_idHelper->is_trt(ModuleID)) + + } + else if (m_idHelper->is_trt(ModuleID)) // trt modules { if (m_trtIdHelper->is_barrel(ModuleID)) { ScaleFactor=m_ScaleTRTBarrel; @@ -738,19 +745,33 @@ namespace InDetAlignment else { // systematic misalignments if (m_MisalignmentMode/10==1) { - //radial misalignments - double deltaR; - if (m_MisalignmentMode==11) { - //R deltaR = radial expansion - if (m_idHelper->is_trt(ModuleID) && abs(m_trtIdHelper->barrel_ec(ModuleID))==2) { - //radial mode cannot handle TRT endcap, sorry - deltaR = 0.; - if (msgLvl(MSG::DEBUG)) msg() << "will not move TRT endcap for radial distortion " << endreq; - } else { - //deltaR = 0.5 * cos ( 2*phi ) * r/maxRadius * maxDeltaR; - deltaR = r/maxRadius * maxDeltaR; //scale linearly in r - } - } else if (m_MisalignmentMode==12) { + //R deltaR = radial expansion + double deltaR; + // 11: radial misalignments + // 10/ May /2019 Salva --> allow radial distortion only of the barrel elements + if (m_MisalignmentMode==11) { + //R deltaR = radial expansion + if (m_idHelper->is_trt(ModuleID) && abs(m_trtIdHelper->barrel_ec(ModuleID))==2) { + //radial mode cannot handle TRT endcap, sorry + deltaR = 0.; + if (msgLvl(MSG::DEBUG)) msg() << " -> will not move TRT endcap for radial distortion " << endreq; + } + else if (m_idHelper->is_pixel(ModuleID) && !m_pixelIdHelper->is_barrel(ModuleID)) { + deltaR = 0.; + if (msgLvl(MSG::DEBUG)) msg() << " -> will not move PIX endcap for radial distortion (mode " + << m_MisalignmentMode << ")" << endreq; + } + else if (m_idHelper->is_sct(ModuleID) && !m_sctIdHelper->is_barrel(ModuleID)) { + deltaR = 0.; + if (msgLvl(MSG::DEBUG)) msg() << " -> will not move SCT endcap for radial distortion (mode " + << m_MisalignmentMode << ")" << endreq; + } + else { + //deltaR = 0.5 * cos ( 2*phi ) * r/maxRadius * maxDeltaR; + deltaR = r/maxRadius * maxDeltaR; //scale linearly in r + } + // end of radial (mode 11) + } else if (m_MisalignmentMode==12) { //Phi deltaR = elliptical (egg-shape) if (m_idHelper->is_trt(ModuleID) && abs(m_trtIdHelper->barrel_ec(ModuleID))==2) { //elliptical mode cannot handle TRT endcap, sorry diff --git a/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/RadDamageUtil.cxx b/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/RadDamageUtil.cxx index 5bbfff4583c4370a005029a3cf1c44c2b5f6ea40..7905cf85df7bab71b8ec4c29d11dc6a85a3e8c27 100644 --- a/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/RadDamageUtil.cxx +++ b/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/RadDamageUtil.cxx @@ -46,13 +46,13 @@ RadDam::RadDamageUtil::RadDamageUtil(const std::string& type, const std::string& AthAlgTool(type,name,parent), m_defaultRamo( 1 ), m_defaultEField( 1 ), + m_EfieldInterpolator(""), m_betaElectrons(4.5e-16), m_betaHoles(6.0e-16), - m_EfieldInterpolator(nullptr), m_saveDebugMaps(false), m_rndmSvc("AtDSFMTGenSvc",name), m_rndmEngineName("PixelDigitization"), - m_rndmEngine(0) + m_rndmEngine(nullptr) { declareProperty("RndmSvc", m_rndmSvc, "Random Number Service used in RadDamageUtil"); declareProperty("RndmEngine", m_rndmEngineName, "Random engine name"); @@ -239,12 +239,10 @@ double RadDam::RadDamageUtil::weighting2D(double x, double z, double Lx, double //========================================= // G E N E R A T E E - F I E L D M A P //========================================= -const StatusCode RadDam::RadDamageUtil::generateEfieldMap( TH1F* eFieldMap, InDetDD::PixelModuleDesign* module ){ +const StatusCode RadDam::RadDamageUtil::generateEfieldMap( TH1F*& eFieldMap, InDetDD::PixelModuleDesign* module ){ //TODO: from DB double biasVoltage = 600.; - double depletionVoltage = 80.; - double depletionLength = 0.2; double sensorThickness = module->thickness(); //default should be 0.2? double fluence = 8.;//*e14 neq/cm^2 eFieldMap = new TH1F("hefieldz","hefieldz",200,0,sensorThickness*1e3); @@ -291,7 +289,7 @@ const StatusCode RadDam::RadDamageUtil::generateEfieldMap( TH1F* eFieldMap, InDe return StatusCode::SUCCESS; } -StatusCode RadDam::RadDamageUtil::generateEfieldMap( TH1F* &eFieldMap, InDetDD::PixelModuleDesign* module, double fluence, double biasVoltage, int layer, std::string TCAD_list, bool interpolate ){ +StatusCode RadDam::RadDamageUtil::generateEfieldMap( TH1F* &eFieldMap, InDetDD::PixelModuleDesign* /*module*/, double fluence, double biasVoltage, int layer, std::string TCAD_list, bool interpolate ){ TString id; //TODO adapt saving location for documentation of E field interpolation @@ -379,7 +377,6 @@ const StatusCode RadDam::RadDamageUtil::generateDistanceTimeMap( TH2F* &distance ATH_MSG_DEBUG ("Did not find time and/or distance maps. Will compute them from the E-field map.."); for (int i=1; i<= distanceMap_e->GetNbinsX(); i++){ //Loop over initial position of charge carrier (in z) - double z_i = distanceMap_e->GetXaxis()->GetBinCenter(i); double time_e = 0.; //ns double time_h = 0.; //ns double distanceTravelled_e=0; //mm diff --git a/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/RadDamageUtil.h b/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/RadDamageUtil.h index fcfb0597a3815a812475014618ba49f718d75bfd..b4bac6410ecec4a40a364e08e9c7d345b48785cd 100644 --- a/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/RadDamageUtil.h +++ b/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/RadDamageUtil.h @@ -51,7 +51,7 @@ public: virtual ~RadDamageUtil(); StatusCode initTools(); const StatusCode generateRamoMap(TH3F* ramPotentialMap, InDetDD::PixelModuleDesign* module); - const StatusCode generateEfieldMap(TH1F* eFieldMap, InDetDD::PixelModuleDesign* module); + const StatusCode generateEfieldMap(TH1F*& eFieldMap, InDetDD::PixelModuleDesign* module); StatusCode generateEfieldMap(TH1F* &eFieldMap, InDetDD::PixelModuleDesign* module, double fluence, double biasVoltage, int layer, std::string TCAD_list, bool interpolate); const StatusCode generateDistanceTimeMap( TH2F* &distanceMap_e, TH2F* &distanceMap_h, TH1F* &timeMap_e, TH1F* &timeMap_h, TH2F* &lorentzMap_e, TH2F* &lorentzMap_h, TH1F* &eFieldMap, InDetDD::PixelModuleDesign* module); diff --git a/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/SensorSim3DTool.cxx b/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/SensorSim3DTool.cxx index 33ea2736b868acbefd84211b6e98e008af722788..7b0a3ee66afe8ac343732cd57a3b099c267aba8a 100644 --- a/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/SensorSim3DTool.cxx +++ b/InnerDetector/InDetDigitization/PixelRadDamDigitization/src/SensorSim3DTool.cxx @@ -96,49 +96,54 @@ } else if (m_fluence == 1) { - mapsPath_list.push_back(PathResolverFindCalibFile("/afs/cern.ch/user/v/vewallan/public/TCADmaps/outputfiles/phi_0_20V.root")); + //Beginning of Run 2 (measured fluence) + mapsPath_list.push_back(PathResolverFindCalibFile("PixelDigitization/TCAD_IBL_3Dsensors_efields/phi_0.0e+00_20V_270K.root")); fluence_layers.push_back(1e-10); } else if (m_fluence == 2) { - mapsPath_list.push_back(PathResolverFindCalibFile("/afs/cern.ch/user/v/vewallan/public/TCADmaps/outputfiles/phi_1e14_20V.root")); + //Half-way through 2016 (measured fluence) + mapsPath_list.push_back(PathResolverFindCalibFile("PixelDigitization/TCAD_IBL_3Dsensors_efields/phi_5.0e+13_20V_283K.root")); - fluence_layers.push_back(1e14); + fluence_layers.push_back(5e13); } else if (m_fluence == 3) { - mapsPath_list.push_back(PathResolverFindCalibFile("/afs/cern.ch/user/v/vewallan/public/TCADmaps/outputfiles/phi_2e14_30V.root")); + //End of 2016 (measured fluence) + mapsPath_list.push_back(PathResolverFindCalibFile("PixelDigitization/TCAD_IBL_3Dsensors_efields/phi_1.0e+14_20V_283K.root")); - fluence_layers.push_back(2e14); + fluence_layers.push_back(1e14); } else if (m_fluence == 4) { - mapsPath_list.push_back(PathResolverFindCalibFile("/afs/cern.ch/user/v/vewallan/public/TCADmaps/outputfiles/phi_5e14_40V.root")); + //End of 2017 (measured fluence) + mapsPath_list.push_back(PathResolverFindCalibFile("PixelDigitization/TCAD_IBL_3Dsensors_efields/phi_2.5e+14_40V_261K.root")); - fluence_layers.push_back(5e14); + fluence_layers.push_back(2.5e14); } else if (m_fluence == 5) { - mapsPath_list.push_back(PathResolverFindCalibFile("/afs/cern.ch/user/v/vewallan/public/TCADmaps/outputfiles/phi_1e15_50V.root")); + //End of Run 2 (end of 2018) (measured fluence) + mapsPath_list.push_back(PathResolverFindCalibFile("PixelDigitization/TCAD_IBL_3Dsensors_efields/phi_5.0e+14_40V_261K.root")); - fluence_layers.push_back(1e15); + fluence_layers.push_back(5e14); } else if (m_fluence == 6) { - mapsPath_list.push_back(PathResolverFindCalibFile("/afs/cern.ch/user/v/vewallan/public/TCADmaps/outputfiles/phi_5e15_160V.root")); + mapsPath_list.push_back(PathResolverFindCalibFile("PixelDigitization/TCAD_IBL_3Dsensors_efields/phi_5e15_160V.root")); fluence_layers.push_back(5e15); } else if (m_fluence == 7) { - mapsPath_list.push_back(PathResolverFindCalibFile("/afs/cern.ch/user/v/vewallan/public/TCADmaps/outputfiles/phi_6e15_190V_new.root")); + mapsPath_list.push_back(PathResolverFindCalibFile("PixelDigitization/TCAD_IBL_3Dsensors_efields/phi_6e15_190V_new.root")); fluence_layers.push_back(6e15); } else if (m_fluence == 8) { - mapsPath_list.push_back(PathResolverFindCalibFile("/afs/cern.ch/user/v/vewallan/public/TCADmaps/outputfiles/phi_1e16_260V_new.root")); + mapsPath_list.push_back(PathResolverFindCalibFile("PixelDigitization/TCAD_IBL_3Dsensors_efields/phi_1e16_260V_new.root")); fluence_layers.push_back(1e16); } diff --git a/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/AutomatedCheck/acZmumu.py b/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/AutomatedCheck/acZmumu.py index e8e9ddbb119bd154f4bea17ba69f0b387e55a534..fc23753caa263902aedb000e509255ec816df8af 100644 --- a/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/AutomatedCheck/acZmumu.py +++ b/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/AutomatedCheck/acZmumu.py @@ -4,10 +4,11 @@ m_storingFolder = "" m_recordsFileName = "" m_athenaVersion = "" m_testArea = "" +m_packagePath = "" m_theUser = "" -m_scriptName = "runzmumu_UserConstants.py" m_savingFile = "acZmumu_history.txt" m_reconmerge = "merge" #"%" +m_workDirPlatform = "" # options m_minEvents = 10000 @@ -21,23 +22,21 @@ m_dataProject = "data17_13TeV" m_userFiles = 0 # this means all the files m_amitag = "%" m_physicsType = "physics_Main" -m_usingMC = False m_mcDataSetName = "mc16_13TeV.361107.PowhegPythia8EvtGen_AZNLOCTEQ6L1_Zmumu.recon.ESD.e3601_s3126_r10201" +m_scriptName = "runzmumu_UserConstants.py" +m_userDataSet = "NONE" ################################################################################################### def findListOfDataSets(): import os + import sys listOfDataSets = [] - #ami list datasets data18_13TeV.%.physics_Main.merge.DESDM_ZMUMU% - #theAMIsearchCommand = "ami list datasets %s.%%.physics_Main.%s.%s.%s --order run_number --fields events,nfiles" %(m_dataProject, m_reconmerge, m_dataType, m_amitag) - #theAMIsearchCommand = "ami list datasets %s.%%.%s.%s.%s.%s --order run_number --fields events,nfiles" %(m_dataProject, m_physicsType, m_reconmerge, m_dataType, m_amitag) theAMIsearchCommand = "ami list datasets %s.%%.%s.%s.%s.%s --order run_number --fields events,nfiles" %(m_dataProject, m_physicsType, m_reconmerge, m_dataType, m_amitag) - #theAMIsearchCommand = "ami list datasets %s.%%.physics_HardProbes.%s.%s.%s --order run_number --fields events,nfiles" %(m_dataProject, m_reconmerge, m_dataType, m_amitag) - # case of using MC - if (m_usingMC): - theAMIsearchCommand = "ami list datasets %s --order run_number --fields events,nfiles" %(m_mcDataSetName) + # case of using data set provided by the user + if ("NONE" not in m_userDataSet): + theAMIsearchCommand = "ami list datasets %s --fields events,nfiles" %(m_userDataSet) print (" <acZmumu> AMI data set search command: \n --> %s" %(theAMIsearchCommand)) amiReturn = os.popen(theAMIsearchCommand).readlines() @@ -50,10 +49,20 @@ def findListOfDataSets(): if ("events" in theLine): lineWithContent = False # remove the header - if (lineWithContent): + if (lineWithContent and "NONE" in m_userDataSet): theLine.rstrip() # remove trailing blank spaces listOfDataSets.append(theLine) # add this data set + + if ("NONE" not in m_userDataSet): + tempstring = str(m_userDataSet[0:30]) + if (tempstring in theLine): + listOfDataSets.append(m_userDataSet) + # if user provides the data set name, it may happen (if errors) the data set is not found or does not exist + if (len(listOfDataSets) == 0 and "NONE" not in m_userDataSet): + print " <acZmumu> ** WARNING ** user data set: %s not found " %m_userDataSet + sys.exit(" >> STOP excution") + return listOfDataSets ################################################################################################### @@ -98,8 +107,10 @@ def preliminaries (): global m_athenaVersion global m_testArea global m_theUser + global m_packagePath + global m_workDirPlatform - m_athenaVersion, m_testArea, m_theUser = getAthenaBasics () + m_athenaVersion, m_testArea, m_theUser, m_packagePath, m_workDirPlatform = getAthenaBasics () m_year = getYear () # reports folder @@ -133,7 +144,7 @@ def extractRunsAndProperties (listOfDataSets): # the list of data sets can contain dummy lines infoFromAMI = {} - if (len(listOfDataSets)>0): + if (len(listOfDataSets)>0 and ("NONE" in m_userDataSet)): print (" <acZmumu> #data sets= %d" %(len(listOfDataSets))) # extract data set name # first is the data project @@ -173,8 +184,9 @@ def extractRunsAndProperties (listOfDataSets): infoFromAMI[theRunNumber]["dataset"] = "%s%s" %(infoFromAMI[theRunNumber]["dataset"],theDataSet) continue else: - print (" <acZmumu> ERROR ** list of data sets is empty. Stop Execution") - exit () + if ("NONE" in m_userDataSet): + print (" <acZmumu> ERROR ** list of data sets is empty. Stop Execution") + exit () return infoFromAMI @@ -253,6 +265,35 @@ def crossCheckInfo(infoFromAMI, infoFromRecordsFile): ################################################################################################### def submitGridJobs (infoFromAMI, listOfNewRuns, listOfPendingRuns): + + # submitting jobs with real data -> listOfNewRuns must be filled + if (len(listOfNewRuns) > 0): + submitGridJobsListOfRuns (infoFromAMI, listOfNewRuns, listOfPendingRuns) + + # submitting job when the user provides the data set + if ("NONE" not in m_userDataSet): + submitGridJobsUserDataSet () + + return + +################################################################################################### +def submitGridJobsUserDataSet (): + import os + + print " <acZmumu> submitting grid job when user provides the data set name " + theCommand = getGridSubmissionCommand(0, infoFromAMI) + if (m_submitExec): + print (" <acZmumu> m_submitExec = True --> job to be submmited"); + # move to the submission folder + submissionPath = "%s/run" %(m_testArea) + os.chdir(submissionPath) + print (" <acZmumu> path: %s" %(submissionPath)) + os.system(theCommand) + + return + +################################################################################################### +def submitGridJobsListOfRuns (infoFromAMI, listOfNewRuns, listOfPendingRuns): import os listOfSubmittedRuns = [] @@ -349,6 +390,26 @@ def getAthenaBasics (): print (" <acZmumu> ERROR ** no Athena TestArea defined --> job submission is not possible. STOP execution") exit() + workdirplatform = "" + try: + workdirplatform = os.getenv("WorkDir_PLATFORM","") + except: + print (" <acZmumu> ERROR ** no WorkDir_PLATFORM defined --> job submission is not possible. STOP execution") + exit() + + print " == athenabasics == workdirplatform = %s" %workdirplatform + + packagePath = "" + try: + thepwd = os.getcwd() + thisfoldername = os.path.basename(thepwd) + tempList = thepwd.split("athena") + tempword = tempList[-1] + tempList = tempword.split(thisfoldername) + packagePath = tempList[0] + except: + packagePath = "" + # voms proxy must be initiated goodVoms = True vomsInfoReturn = os.popen("voms-proxy-info").readlines() @@ -365,7 +426,7 @@ def getAthenaBasics (): print (" <acZmumu> ERROR ** no voms initiated --> It is not possible to consult AMI. Stop execution") exit() - return (athenaVersion, testArea, theUser) + return (athenaVersion, testArea, theUser, packagePath, workdirplatform) ################################################################################################### def getGridSubmissionCommand(runNumber, infoFromAMI): @@ -373,13 +434,41 @@ def getGridSubmissionCommand(runNumber, infoFromAMI): # build the command for submission #theScript = "%s/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/share/runzmumu_run2paper.py" %(m_testArea) - theScript = "%s/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/share/%s" %(m_testArea, m_scriptName) - theInput = "--inDS=%s" %(infoFromAMI[runNumber]["dataset"]) - theOutput = "--outDS=user.%s.%s_%s_%d_Zmumu_%s_%d " %(m_theUser, m_athenaVersion, m_dataProject, runNumber, m_userLabel, infoFromAMI[runNumber]["attempt"]) - #theOptions = "--nfiles %d --useShortLivedReplicas --forceStaged --nFilesPerJob %d" %(infoFromAMI[runNumber]["nfiles"], 20) - theOptions = "--nfiles %d --useShortLivedReplicas --forceStaged --excludedSite=ANALY_HPC2N" %(infoFromAMI[runNumber]["nfiles"]) - - theCommand = "pathena %s %s %s %s" %(theScript, theInput, theOutput, theOptions) + #theScript = "%s/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/share/%s" %(m_testArea, m_scriptName) + theScript = "%s%sshare/%s" %(m_testArea, m_packagePath, m_scriptName) + + theInput = "NONE" + if (runNumber>0): + theInput = "--inDS=%s" %(infoFromAMI[runNumber]["dataset"]) + else: + if ("NONE" not in m_userDataSet): + theInput = "--inDS=%s" %m_userDataSet + if ("NONE" in theInput): + sys.exit(" <acZmumu> ** ERROR ** no input available for the grid submission command. ** STOP execution **") + + theOuput = "NONE" + if (runNumber>0): + theOutput = "--outDS=user.%s.%s_%s_%d_Zmumu_%s_%d " %(m_theUser, m_athenaVersion, m_dataProject, runNumber, m_userLabel, infoFromAMI[runNumber]["attempt"]) + else: + if ("NONE" not in m_userDataSet): + theOutput = "--outDS=user.%s.%s_Zmumu_%s" %(m_theUser, m_athenaVersion, m_userLabel) + if ("NONE" in theOutput): + sys.exit(" <acZmumu> ** ERROR ** no output available for the grid submission command. ** STOP execution **") + + # warning: if one wants to limit the file per job just add to the options: --nFilesPerJob Nfiles + #theOptions = "--nfiles %d --useShortLivedReplicas --forceStaged --site=ANALY_ECDF_SL7" %(infoFromAMI[runNumber]["nfiles"]) + + theOptions = "NONE" + if (runNumber>0): + theOptions = "--nfiles %d --useShortLivedReplicas --forceStaged" %(infoFromAMI[runNumber]["nfiles"]) + else: + if ("NONE" not in m_userDataSet): + theOptions = "--useShortLivedReplicas --forceStaged" + + theExtraOptions = "" + theExtraOptions = "--cmtConfig %s --excludedSite=ANALY_HPC2N,ANALY_RHUL_SL6,ANALY_JINR_MIG,ANALY_IHEP,ANALY_JINR,ANALY_CSCS-HPC" %m_workDirPlatform + + theCommand = "pathena %s %s %s %s %s" %(theScript, theInput, theOutput, theOptions, theExtraOptions) print "%s " %theCommand return theCommand @@ -387,13 +476,14 @@ def getGridSubmissionCommand(runNumber, infoFromAMI): ################################################################################################### def updateRecordsFile(listOfSubmittedRuns, infoFromAMI): - print (" <acZmumu> updateRecordsFile --> %s " %(m_recordsFileName)) - fileToUpdate = open(m_recordsFileName, "a"); - fileToUpdate.write("\n") - for runNumber in listOfSubmittedRuns: - fileToUpdate.write("%d:%s\n" %(runNumber, infoFromAMI[runNumber])) + if ("NONE" in m_userDataSet): + print (" <acZmumu> updateRecordsFile --> %s " %(m_recordsFileName)) + fileToUpdate = open(m_recordsFileName, "a"); + fileToUpdate.write("\n") + for runNumber in listOfSubmittedRuns: + fileToUpdate.write("%d:%s\n" %(runNumber, infoFromAMI[runNumber])) - fileToUpdate.close() + fileToUpdate.close() return @@ -407,9 +497,6 @@ def welcomeBanner (): print ("\n") print (" config:") print (" ** Exec: %r" %m_submitExec) - print (" ** using MC? %r" %m_usingMC) - if (m_usingMC): - print (" ** mc data set %s" %m_mcDataSetName) print (" ** data project: %s " %m_dataProject) print (" ** min events: %d" %m_minEvents) print (" ** min Run: %d" %m_firstRun) @@ -421,6 +508,9 @@ def welcomeBanner (): if (m_userFiles > 0): print (" ** user requested files: %d" %m_userFiles) print (" ** AMI tag: %s" %m_amitag) + print " ** script: %s" %m_scriptName + if ("NONE" not in m_userDataSet): + print " ** user data set: %s" %m_userDataSet print ("\n") return @@ -446,22 +536,22 @@ def optParsing(): p_amitag = m_amitag p_dataProject = m_dataProject p_physicsType = m_physicsType - p_usingMC = m_usingMC - p_mcDataSetName = m_mcDataSetName + p_scriptName = m_scriptName + p_userDataSet = m_userDataSet parser = OptionParser() parser.add_option("--amiTag", dest="p_amitag", help="Name of the requested AMI tag (example: r10258_r10258_p3399). Wild card is also possible. Default %s" %(p_amitag), default = p_amitag) parser.add_option("--dataProject", dest="p_dataProject", help="data project of the data sets (examples: data17_13TeV). Default %s" %(p_dataProject), default = p_dataProject) + parser.add_option("--dataSet", dest="p_userDataSet", help="User defined data set. Default %s" %(p_userDataSet), default = p_userDataSet) parser.add_option("--dataType", dest="p_dataType", help="User defined data type (examples: DAOD_ZMUMU, DESDM_MCP). Default %s" %(p_dataType), default = p_dataType) - parser.add_option("--dataSet", dest="p_mcDataSetName", help="User defined full data set name", default = p_mcDataSetName) parser.add_option("--EXEC", dest="p_submitExec", help="Submit the Grid jobs. Default: no submission", action="store_true", default = False) parser.add_option("--firstRun", dest="p_firstRun", help="First run number (inclusive). Default %s" %(p_firstRun), default = p_firstRun) parser.add_option("--lastRun", dest="p_lastRun", help="Last run number (inclusive). Default %s" %(p_lastRun), default = p_lastRun) - parser.add_option("--MC", dest="p_usingMC", help="Use MC. The data set must be provided in full. Default: no MC", action="store_true", default = p_usingMC) parser.add_option("--minEvents", dest="p_minEvents", help="Minimum number of events. Default %s" %(p_minEvents), default = p_minEvents) parser.add_option("--nFiles", dest="p_userFiles", help="User defined number of files. Default %s = all the available files" %(p_userFiles), default = p_userFiles) parser.add_option("--run", dest="p_userRun", help="Run number in case of targetting a single run. Default %s" %(p_userRun), default = p_userRun) parser.add_option("--physicsType", dest="p_physicsType", help="Physics type to use (physics_Main, Hardprobes...) Default %s" %(p_physicsType), default = p_physicsType) + parser.add_option("--script", dest="p_scriptName", help="Name of the python script to be executed. Default %s" %p_scriptName, default = p_scriptName) parser.add_option("--userLabel", dest="p_userLabel", help="User defined label. Default %s" %(p_userLabel), default = p_userLabel) (config, sys.argv[1:]) = parser.parse_args(sys.argv[1:]) @@ -517,8 +607,8 @@ if __name__ == '__main__': m_amitag = config.p_amitag m_dataProject = config.p_dataProject m_physicsType = config.p_physicsType - m_usingMC = config.p_usingMC - m_mcDataSetName = config.p_mcDataSetName + m_scriptName = config.p_scriptName + m_userDataSet = config.p_userDataSet welcomeBanner () preliminaries () diff --git a/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/share/runzmumu_UserConstants.py b/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/share/runzmumu_UserConstants.py index 9f1d3b64697b0afda64a8db608e99d58cce3cb6c..bb7d8fcd999d0fc623eec4d31527e66b0f044e5b 100644 --- a/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/share/runzmumu_UserConstants.py +++ b/InnerDetector/InDetMonitoring/InDetPerformanceMonitoring/share/runzmumu_UserConstants.py @@ -32,7 +32,7 @@ monitoringAllTracks = True useGRL = False # MC -MC_bool = False +MC_bool = True # do Trigger DoTrigger = False @@ -41,15 +41,15 @@ DoTrigger = False grid_bool = True # handle input constants -readPool = False # default True +readPool = True # default True readLocalDynamicDB = False # default False -#inputConstants = "step8_Iter1_AlignmentConstants.root" -#inputdb = "step8_Iter1_mycool.db" -inputConstants = "ReAlign_2018_L6_Step28_L3.root" +#inputConstants = "ReAlign_2018_L6_Step28_L3.root" +#inputConstants = "step27_358395_AlignmentConstants_Iter0_Block00.root" +inputConstants = "MisalignmentSet11_p01.pool.root" inputdb = "Javi_Test_mycool.db" -#inputConstants = "MisalignmentSet11_p01.pool.root" -#inputConstants = "AlignmentConstants_Galo_2018BaseLine.root" +#inputdb = "step8_Iter1_mycool.db" + if (readPool): print " readPool = True file: %s" %(inputConstants) import socket @@ -87,7 +87,8 @@ print ' ========= runzmumu === config == end == ' #include("InDetSimpleVisual/GetDetectorPositions.py") if (grid_bool): - PoolInput = ["/afs/cern.ch/user/m/martis/mywork/ZmumuNtuples/InputFileForGridJobs/data18_13TeV.00348354.physics_Main.merge.DESDM_ZMUMU.f920_m1831_f920_m1951._0001.1"] + # PoolInput = ["/afs/cern.ch/user/m/martis/mywork/ZmumuNtuples/InputFileForGridJobs/data18_13TeV.00348354.physics_Main.merge.DESDM_ZMUMU.f920_m1831_f920_m1951._0001.1"] + PoolInput = ["/eos/user/m/martis/data/data18_13TeV/data18_13TeV.00352436.physics_Main.merge.DAOD_ZMUMU.f938_m1831_f938_m1982._0027.1"] if (MC_bool): PoolInput = ["/eos/user/m/martis/data/mc16_13TeV/folder_mc16_13TeV.361107.PowhegPythia8EvtGen_AZNLOCTEQ6L1_Zmumu.recon.ESD.e3601_s3126_r10201/ESD.13642341._000503.pool.root.1"] @@ -189,6 +190,7 @@ DetFlags.Calo_setOff() DetFlags.Muon_setOn() +print " == runzmumu == user may define his favourite alignment == start == " from IOVDbSvc.CondDB import conddb if (useIDADynamicFolders): if (False): @@ -196,7 +198,7 @@ if (useIDADynamicFolders): conddb.addOverride("/Indet/AlignL1/ID" ,"IndetAlignL1ID-R2dynamic_2018_ReAlign_Initial") conddb.addOverride("/Indet/AlignL2/PIX" ,"IndetAlignL2PIX-R2dynamic_2018_ReAlign_Initial") conddb.addOverride("/Indet/AlignL2/SCT" ,"IndetAlignL2SCT-R2dynamic_2018_ReAlign_Initial") - conddb.addOverride("/Indet/AlignL3" ,"IndetIBLDist-R2dynamic_2018_ReAlign_Initial") + conddb.addOverride("/Indet/AlignL3" ,"IndetAlignL3-R2dynamic_2018_ReAlign_Initial") conddb.addOverride("/Indet/IBLDist", "IndetAlignL3-R2dynamic_2018_ReAlign_Initial") conddb.addOverride("/TRT/AlignL1/TRT", "TRTAlignL1-R2dynamic_2018_ReAlign_Initial") conddb.addOverride("/TRT/AlignL2", "TRTAlignL2-R2dynamic_2018_ReAlign_Initial") @@ -228,19 +230,56 @@ if (useIDADynamicFolders): conddb.blockFolder("/Indet/AlignL3") conddb.blockFolder("/TRT/AlignL2") + if (False): + print (" == runzmumu == configuring 2018 ReAlign family (using RunSet2)") + conddb.addOverride("/Indet/AlignL1/ID" ,"InDetAlignL1_ID_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/Indet/AlignL2/PIX" ,"InDetAlignL2PIX_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/Indet/AlignL2/SCT" ,"InDetAlignL2SCT_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/Indet/IBLDist", "InDetAlignIBLDist_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/TRT/AlignL1/TRT", "TRTAlignL1_R2dynamic_data18_2ndBatch_Initial") + #conddb.blockFolder("/Indet/AlignL3") + #conddb.blockFolder("/TRT/AlignL2") + #conddb.addOverride("/Indet/AlignL3" ,"IndetAlignL3-R2dynamic_2018_ReAlign_Initial") + #conddb.addOverride("/Indet/AlignL3" ,"InDetAlignL3_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/TRT/AlignL2", "TRTAlignL2_R2dynamic_data18_2ndBatch_Initial") + + if (True): + print (" == runzmumu == configuring 2018 Salva test") + conddb.addOverride("/Indet/AlignL1/ID", "IndetAlignL1ID-R2dynamic-SALVA-2018-step27-TEST0") + conddb.addOverride("/Indet/AlignL2/PIX", "IndetAlignL2PIX-R2dynamic-SALVA-2018-step27-TEST0") + conddb.addOverride("/Indet/AlignL2/SCT", "IndetAlignL2SCT-R2dynamic-SALVA-2018-step27-TEST0") + conddb.addOverride("/Indet/IBLDist", "IndetAlignIBLDIST-R2dynamic-SALVA-2018-step27-TEST0") + conddb.addOverride("/Indet/AlignL3", "IndetAlignL3-R2dynamic-SALVA-2018-step27-TEST0") + conddb.addOverride("/TRT/AlignL1/TRT", "TRTAlignL1-R2dynamic-SALVA-2018-step27-TEST0") + conddb.addOverride("/TRT/AlignL2", "TRTAlignL2-R2dynamic-SALVA-2018-step27-TEST0") + if readPool and False: + print " == runzmumu == configuring 2018 Salva test == conddb.blockFolder(/Indet/AlignL3)" + conddb.blockFolder("/Indet/AlignL3") + conddb.blockFolder("/TRT/AlignL2") + if (False): + print (" == runzmumu == configuring 2018 Stefano test") + conddb.addOverride("/Indet/AlignL1/ID", "InDetAlignL1_ID_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/Indet/AlignL2/PIX", "InDetAlignL2PIX_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/Indet/AlignL2/SCT", "InDetAlignL2SCT_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/Indet/IBLDist", "InDetAlignIBLDist_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/Indet/AlignL3", "InDetAlignL3_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/TRT/AlignL1/TRT", "TRTAlignL1_R2dynamic_data18_2ndBatch_Initial") + conddb.addOverride("/TRT/AlignL2", "TRTAlignL2_R2dynamic_data18_2ndBatch_Initial") + if readPool and False: + conddb.blockFolder("/Indet/AlignL3") + conddb.blockFolder("/TRT/AlignL2") +print " == runzmumu == user may define his favourite alignment == completed == " ## -blocked_folders = [ - '/LAR/ElecCalibMC/AutoCorr', - ] +blocked_folders = ['/LAR/ElecCalibMC/AutoCorr'] for f in blocked_folders: conddb.blockFolder (f) print " == runzmumu == folder ",f," --> blocked " inputCollectons =[] -if 'inputConstants' in dir(): +if 'inputConstants' in dir() and readPool: inputCollections = [inputConstants] print " == runzmumu == inputConstants in dir() == ", inputConstants diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/share/postInclude.SiHitAnalysis.py b/InnerDetector/InDetValidation/InDetPhysValMonitoring/share/postInclude.SiHitAnalysis.py index e6d37f65690e654139b7aeffb16b31fbb8718442..8f0f2f7967d9a2359b92fd59743d8edb81187d85 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/share/postInclude.SiHitAnalysis.py +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/share/postInclude.SiHitAnalysis.py @@ -1,4 +1,4 @@ -from AtlasGeoModel.InDetGMJobProperties import InDetGeometryFlags +from AtlasGeoModel.InDetGMJobProperties import GeometryFlags as InDetGeometryFlags from HitAnalysis.HitAnalysisConf import SiHitAnalysis topSequence += SiHitAnalysis('PixelHitAnalysis') topSequence.PixelHitAnalysis.CollectionName='PixelHits' diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/PixelNtupleMaker.h b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/PixelNtupleMaker.h index ff8ad29b146bc1f12bbb26189fc68c4f77eebd97..a15e08c8cdb929b6421bd5928733e74d5a1d38e8 100644 --- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/PixelNtupleMaker.h +++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/DerivationFrameworkInDet/PixelNtupleMaker.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ #ifndef DERIVATIONFRAMEWORK_PIXELNTUPLEMAKER_H diff --git a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/PixelNtupleMaker.cxx b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/PixelNtupleMaker.cxx index f3bac6a615452eda31285883e9a41aecec5d7b0b..a0e23fbbd86bd4dad7ce3d2283b611f6d4d2f3c2 100644 --- a/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/PixelNtupleMaker.cxx +++ b/PhysicsAnalysis/DerivationFramework/DerivationFrameworkInDet/src/PixelNtupleMaker.cxx @@ -117,6 +117,8 @@ bool DerivationFramework::PixelNtupleMaker::eventPassesFilter() const { std::vector<int> clusterIsolation20x4; std::vector<int> numTotalClustersPerModule; std::vector<int> numTotalPixelsPerModule; + std::vector<int> moduleBSerr; + std::vector<int> moduleDCSstate; std::vector<float> moduleBiasVoltage; std::vector<float> moduleTemperature; std::vector<float> moduleLorentzShift; @@ -179,6 +181,16 @@ bool DerivationFramework::PixelNtupleMaker::eventPassesFilter() const { unbiasedResidualY.push_back(msos->unbiasedResidualY()); unbiasedPullX.push_back(msos->auxdata<float>("unbiasedPullX")); unbiasedPullY.push_back(msos->auxdata<float>("unbiasedPullY")); + + moduleBSerr.push_back((*clus_itr)->auxdata<int>("isBSError")); + + if ((*clus_itr)->auxdata<std::string>("DCSState")=="ON" || (*clus_itr)->auxdata<std::string>("DCSState")=="READY") { + moduleDCSstate.push_back(0); + } + else { + moduleDCSstate.push_back(1); + } + moduleBiasVoltage.push_back((*clus_itr)->auxdata<float>("BiasVoltage")); moduleTemperature.push_back((*clus_itr)->auxdata<float>("Temperature")); moduleLorentzShift.push_back((*clus_itr)->auxdata<float>("LorentzShift")); @@ -405,6 +417,8 @@ bool DerivationFramework::PixelNtupleMaker::eventPassesFilter() const { static SG::AuxElement::Decorator<std::vector<int>> ClusterIsolation20x4("ClusterIsolation20x4"); static SG::AuxElement::Decorator<std::vector<int>> NumTotalClustersPerModule("NumTotalClustersPerModule"); static SG::AuxElement::Decorator<std::vector<int>> NumTotalPixelsPerModule("NumTotalPixelsPerModule"); + static SG::AuxElement::Decorator<std::vector<int>> ModuleBSError("ModuleBSError"); + static SG::AuxElement::Decorator<std::vector<int>> ModuleDCSState("ModuleDCSState"); static SG::AuxElement::Decorator<std::vector<float>> ModuleBiasVoltage("ModuleBiasVoltage"); static SG::AuxElement::Decorator<std::vector<float>> ModuleTemperature("ModuleTemperature"); static SG::AuxElement::Decorator<std::vector<float>> ModuleLorentzShift("ModuleLorentzShift"); @@ -421,8 +435,8 @@ bool DerivationFramework::PixelNtupleMaker::eventPassesFilter() const { static SG::AuxElement::Decorator<std::vector<std::vector<float>>> SiHitEndPosY("SiHitEndPosY"); static SG::AuxElement::Decorator<std::vector<std::vector<float>>> SiHitEnergyDeposit("SiHitEnergyDeposit"); - d0err(*tp) = (*trk)->definingParametersCovMatrixVec().at(0); - z0err(*tp) = (*trk)->definingParametersCovMatrixVec().at(2); + d0err(*tp) = TMath::Sqrt((*trk)->definingParametersCovMatrix()(0,0)); + z0err(*tp) = TMath::Sqrt((*trk)->definingParametersCovMatrix()(1,1)); qOverPerr(*tp) = TMath::Sqrt((*trk)->definingParametersCovMatrix()(4,4)); HoleIndex(*tp) = holeIndex; @@ -458,6 +472,8 @@ bool DerivationFramework::PixelNtupleMaker::eventPassesFilter() const { ClusterIsolation20x4(*tp) = clusterIsolation20x4; NumTotalClustersPerModule(*tp) = numTotalClustersPerModule; NumTotalPixelsPerModule(*tp) = numTotalPixelsPerModule; + ModuleBSError(*tp) = moduleBSerr; + ModuleDCSState(*tp) = moduleDCSstate; ModuleBiasVoltage(*tp) = moduleBiasVoltage; ModuleTemperature(*tp) = moduleTemperature; ModuleLorentzShift(*tp) = moduleLorentzShift; diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/LongLivedParticleDPDMaker/KinkTrkSingleJetMetFilterTool.h b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/LongLivedParticleDPDMaker/KinkTrkSingleJetMetFilterTool.h index 8dedf66cd6fc572857455dad113a368d0346f514..3ee9418a6226b02636fd289295f5eb79609acffc 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/LongLivedParticleDPDMaker/KinkTrkSingleJetMetFilterTool.h +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/LongLivedParticleDPDMaker/KinkTrkSingleJetMetFilterTool.h @@ -40,6 +40,9 @@ namespace DerivationFramework { private: mutable unsigned int m_ntot; mutable unsigned int m_npass; + + ToolHandle<CP::IMuonSelectionTool> m_muonSelectionTool; + bool m_passAll; bool m_LeptonVeto; bool m_isolatedTrack; @@ -47,7 +50,6 @@ namespace DerivationFramework { std::string m_jetSGKey; std::string m_metSGKey; std::string m_metTerm; - ToolHandle<CP::IMuonSelectionTool> m_muonSelectionTool; std::string m_muonSGKey; std::string m_muonIDKey; std::string m_electronSGKey; diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/DVFlags.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/DVFlags.py index 5215478b403b7d02864fbd0258434e747d6e9097..576407591e3786777e1894c034179bc03784509c 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/DVFlags.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/DVFlags.py @@ -10,6 +10,7 @@ primRPVLLDESDM=jobproperties.PrimaryDPDFlags_RPVLLStream ## TriggerAPI ## from LongLivedParticleDPDMaker.RPVLLTriggers import RPVLLTriggers apitriggers = RPVLLTriggers() +from LongLivedParticleDPDMaker.RPVLLTriggers import rpvllTrig class DV_containerFlags(JobProperty): @@ -37,7 +38,7 @@ class DV_MultiJetTriggerFlags(JobProperty): "HLT_7j25_gsc50_boffperf_split_L14J20" ]#gsc triggers += ["HLT_2j275_j140","HLT_2j250_j120","HLT_2j220_j120"]#3jet triggers += ["HLT_5j85_L14J15"] # 2018 5 jet - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggers += apitriggers.getDVMultiJetTriggers() ## TriggerAPI pass primRPVLLDESDM.add_JobProperty(DV_MultiJetTriggerFlags) @@ -164,7 +165,7 @@ class DV_MuonBarrelFilterFlags(JobProperty): cutEtMin=60.0*Units.GeV cutEtaMax=1.1 triggers=["HLT_mu60_0eta105_msonly"] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggers += apitriggers.getDVMuonBarrelTriggers() ## TriggerAPI nPassed=1 pass @@ -177,7 +178,7 @@ class DV_MuonFullMSFilterFlags(JobProperty): cutEtMin=80.0*Units.GeV cutEtaMax=2.5 triggers=["HLT_mu80_msonly_3layersEC"] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggers += apitriggers.getDVMuonFullMSTriggers() ## TriggerAPI nPassed=1 pass @@ -192,7 +193,7 @@ class DV_PhotonFilterFlags(JobProperty): cutIsEM="Loose" triggers=["HLT_g140_loose"] triggers+=["HLT_g140_tight","HLT_g200_loose"]#2017 - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggers += apitriggers.getDVPhotonTriggers() ## TriggerAPI prescale=20 nPassed=1 @@ -225,7 +226,7 @@ class DV_METFilterFlags(JobProperty): triggers+=[ "HLT_xe110_pufit_xe70_L1XE50" ] #2018 primary triggers+=[ "HLT_xe110_pufit_xe65_L1XE55","HLT_xe100_pufit_xe75_L1XE60", "HLT_xe110_pufit_xe65_L1XE60" ] #2018 backup - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggers += apitriggers.getDVMETTriggers() ## TriggerAPI pass primRPVLLDESDM.add_JobProperty(DV_METFilterFlags) diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/DiLepFlags.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/DiLepFlags.py index 1a8e1c94d728049ca137b4c8beda123ad20a8a51..f510b356b47b06eadf4d89d9ec0ab1856468becb 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/DiLepFlags.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/DiLepFlags.py @@ -10,6 +10,8 @@ primRPVLLDESDM = jobproperties.PrimaryDPDFlags_RPVLLStream ## TriggerAPI ## from LongLivedParticleDPDMaker.RPVLLTriggers import RPVLLTriggers apitriggers = RPVLLTriggers() +from LongLivedParticleDPDMaker.RPVLLTriggers import rpvllTrig + class DiLep_FilterFlags(JobProperty): statusOn = True @@ -17,16 +19,16 @@ class DiLep_FilterFlags(JobProperty): StoredValue = True SiPhTriggers = ["HLT_g140_loose", "HLT_g200_loose", "HLT_g200_loose_L1EM24VHIM"] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: SiPhTriggers += apitriggers.getDiLepSiPhTriggers() ## TriggerAPI DiPhTriggers = ["HLT_2g50_loose_L12EM20VH", "HLT_2g60_loose_L12EM20VH"] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: DiPhTriggers += apitriggers.getDiLepDiPhTriggers() ## TriggerAPI SiMuTriggers = ["HLT_mu80_msonly_3layersEC"] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: SiMuTriggers += apitriggers.getDiLepSiMuTriggers() ## TriggerAPI SiMuBaTriggers = ["HLT_mu60_0eta105_msonly"] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: SiMuBaTriggers += apitriggers.getDiLepSiMuBaTriggers() ## TriggerAPI ElEtaMax = 2.5 diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/EmergingFlags.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/EmergingFlags.py index 9d14bc2849db8813cf79bcd8de273488ddde77f7..ae7464deaa27b7a305db397dc39a62812dae8e62 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/EmergingFlags.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/EmergingFlags.py @@ -10,6 +10,7 @@ primRPVLLDESDM = jobproperties.PrimaryDPDFlags_RPVLLStream ## TriggerAPI ## from LongLivedParticleDPDMaker.RPVLLTriggers import RPVLLTriggers apitriggers = RPVLLTriggers() +from LongLivedParticleDPDMaker.RPVLLTriggers import rpvllTrig class Emerging_FilterFlags(JobProperty): statusOn = True @@ -26,7 +27,7 @@ class Emerging_FilterFlags(JobProperty): "HLT_4j140", "HLT_4j150" ] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: Triggers += apitriggers.getEmergingTriggers() ## TriggerAPI primRPVLLDESDM.add_JobProperty(Emerging_FilterFlags) diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/HVFlags.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/HVFlags.py index f18fd997220d096d57c28e39624e987d43a3bd3c..850462b1bdd4cb6b0b83c9b494e73194ae9a9bb1 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/HVFlags.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/HVFlags.py @@ -10,6 +10,8 @@ primRPVLLDESDM=jobproperties.PrimaryDPDFlags_RPVLLStream ## TriggerAPI ## from LongLivedParticleDPDMaker.RPVLLTriggers import RPVLLTriggers apitriggers = RPVLLTriggers() +from LongLivedParticleDPDMaker.RPVLLTriggers import rpvllTrig + class HV_MuvtxTriggerFlags(JobProperty): statusOn = True @@ -22,7 +24,7 @@ class HV_MuvtxTriggerFlags(JobProperty): #"HLT_j30_muvtx_L1MU4_UNPAIRED_ISO", #EMPTY and UNPAIRED_ISO triggers are currently in physics_Late, and thus not part of DRAW_RPVLL ] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: TriggerNames += apitriggers.getHVMuvtxTriggers() ## TriggerAPI pass primRPVLLDESDM.add_JobProperty(HV_MuvtxTriggerFlags) @@ -34,7 +36,7 @@ class HV_prescaledMuvtxTriggerFlags(JobProperty): TriggerNames = [ "HLT_j30_muvtx_noiso", ] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: TriggerNames += apitriggers.getHVprescaledMuvtxTriggers() ## TriggerAPI Prescale = 1 pass @@ -71,7 +73,7 @@ class HV_CalRatioTriggerFlags(JobProperty): #"HLT_j30_jes_cleanLLP_PS_llp_noiso_L1TAU8_UNPAIRED_ISO" #EMPTY and UNPAIRED_ISO triggers are currently in physics_Late, and thus not part of DRAW_RPVLL ] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: TriggerNames += apitriggers.getHVCalRatioTriggers() ## TriggerAPI pass diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/HipsFlags.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/HipsFlags.py index 1f8e749bfef38fd157fa9ea487749b3d99923e69..8ecb80538bb839c2303a7cab6327ba3841a0dd17 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/HipsFlags.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/HipsFlags.py @@ -15,13 +15,15 @@ primHIPsDESD=jobproperties.PrimaryDPDFlags_HIPsStream ## TriggerAPI ## from LongLivedParticleDPDMaker.RPVLLTriggers import RPVLLTriggers apitriggers = RPVLLTriggers() +from LongLivedParticleDPDMaker.RPVLLTriggers import rpvllTrig + class HipsTriggerFilterExpression(JobProperty): statusOn = True allowedTypes = ['bool'] StoredValue = True triggers = ['HLT_g0_hiptrt_L1EM18VH', 'HLT_g0_hiptrt_L1EM20VH', 'HLT_g0_hiptrt_L1EM20VHI', 'HLT_g0_hiptrt_L1EM22VHI', 'HLT_g0_hiptrt_L1EM24VHI', 'HLT_g0_hiptrt_L1EM24VHIM'] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggers += apitriggers.getHIPsTriggers() # TriggerAPI pass primHIPsDESD.add_JobProperty(HipsTriggerFilterExpression) diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/KinkedTrackFlags.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/KinkedTrackFlags.py index b86cc799d17682d5ba54f850a887e46ecdad7c02..309ae989064c319261d6e6eeaeefdf2afaeacf39 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/KinkedTrackFlags.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/KinkedTrackFlags.py @@ -24,6 +24,8 @@ primRPVLLDESDM=jobproperties.PrimaryDPDFlags_RPVLLStream ## TriggerAPI ## from LongLivedParticleDPDMaker.RPVLLTriggers import RPVLLTriggers apitriggers = RPVLLTriggers() +from LongLivedParticleDPDMaker.RPVLLTriggers import rpvllTrig + class KinkedTrack_containerFlags(JobProperty): statusOn = True @@ -151,6 +153,7 @@ class KinkedTrack_singleJetMetFilterFlags(JobProperty): 'HLT_xe110_pufit_xe70_L1XE50', 'HLT_xe110_pufit_xe65_L1XE55', 'HLT_xe110_pufit_xe65_L1XE60', + 'HLT_xe110_pufit_xe65_L1XE50', 'HLT_xe110_L1XE60', 'HLT_xe110_mht_L1XE60', 'HLT_xe110_mht_L1XE50', @@ -174,7 +177,7 @@ class KinkedTrack_singleJetMetFilterFlags(JobProperty): 'HLT_xe120_pufit_L1XE60', 'HLT_xe130_mht_L1XE50' ] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggerNames += apitriggers.getKinkedTrackJetMetTriggers() ## TriggerAPI cutsEtMin = [80.0*Units.GeV, 40.0*Units.GeV] cutsEtMinForStublet = [90.0*Units.GeV, 40.0*Units.GeV] @@ -184,7 +187,7 @@ class KinkedTrack_singleJetMetFilterFlags(JobProperty): cutEtaMax = 3.2 doLeptonVeto = True requireIsolatedTrack = True - electronIDKey = "Tight" + electronIDKey = "LHTight" muonIDKey = "Medium" leptonPtMax = 20.0*Units.GeV leptonEtaMax = 2.5 @@ -235,13 +238,15 @@ class KinkedTrack_ZeeFilterFlags(JobProperty): 'HLT_e28_lhtight_ivarloose', 'HLT_e28_lhtight_nod0_iloose', 'HLT_e28_lhtight_nod0_ivarloose', + 'HLT_e60_lhmedium_nod0', + 'HLT_e140_lhloose_nod0' ] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggerNames += apitriggers.getKinkedTrackZeeTriggers() ## TriggerAPI doTriggerMatch = False electronPtMin = 40*Units.GeV electronEtaMax = 2.5 - electronIDKeys = ["Tight"] + electronIDKeys = ["LHTight"] clusterEtMin = 15*Units.GeV clusterEtaMax = 2.5 diElectronMassLow = (91.1876-40)*Units.GeV @@ -270,7 +275,7 @@ class KinkedTrack_ZmumuFilterFlags(JobProperty): 'HLT_mu26_imedium', 'HLT_mu26_ivarmedium', ] - if apitriggers.doTriggerAPI: + if rpvllTrig.doRPVLLTriggerAPI: triggerNames += apitriggers.getKinkedTrackZmumuTriggers() ## TriggerAPI doTriggerMatch = False muonPtMin = 40*Units.GeV diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/RPVLLTriggers.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/RPVLLTriggers.py index d3ceb0a0b9974ea61c295c08707d4d4ceade5a43..7dd246e9a379161d6f8c33d5540de5563c88ab9e 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/RPVLLTriggers.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/python/RPVLLTriggers.py @@ -1,6 +1,11 @@ from TriggerMenu.api.TriggerAPI import TriggerAPI from TriggerMenu.api.TriggerEnums import TriggerPeriod, TriggerType +from AthenaCommon.JobProperties import JobProperty, JobPropertyContainer +from AthenaCommon.JobProperties import jobproperties + +import AthenaCommon.SystemOfUnits as Units + # general function to get current menu unprescaled triggers for given trigger type #def getTriggerList( trigger_type, matching_pattern="", rejection_pattern="", test=[] ): @@ -155,5 +160,19 @@ class RPVLLTriggers: HIPsList = getTriggerList( TriggerType.exotics, "hiptrt" ) return HIPsList - # on / off switch - doTriggerAPI = True + + +# Flags to turn RPVLL TriggerAPI implementation on/off +class RPVLLTriggerAPIFlags(JobPropertyContainer): + """ RPV/LL TriggerAPI flag container """ + +jobproperties.add_Container(RPVLLTriggerAPIFlags) + +rpvllTrig=jobproperties.RPVLLTriggerAPIFlags + +class doRPVLLTriggerAPI(JobProperty): + statusOn = True + allowedTypes = ["bool"] + StoredValue = True + pass +rpvllTrig.add_JobProperty(doRPVLLTriggerAPI) diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/share/PhysDESDM_HNL.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/share/PhysDESDM_HNL.py index b4074f11b12abe1a40239bd1ab7d8473669004ae..975752ba7af4b0072432bd9adb0e9d158035be4a 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/share/PhysDESDM_HNL.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/share/PhysDESDM_HNL.py @@ -6,8 +6,9 @@ from DerivationFrameworkCore.DerivationFrameworkCoreConf import DerivationFramew ## TriggerAPI ## from LongLivedParticleDPDMaker.RPVLLTriggers import RPVLLTriggers apitriggers = RPVLLTriggers() +from LongLivedParticleDPDMaker.RPVLLTriggers import rpvllTrig apitriggerlist = [] -if apitriggers.doTriggerAPI: +if rpvllTrig.doRPVLLTriggerAPI: apitriggerlist = apitriggers.getHNLTriggers() HnlFilterTool = skimtool( name = "HnlFilterTool", diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/share/PhysDESDM_KinkedTrack.py b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/share/PhysDESDM_KinkedTrack.py index d3053c4a4900a412dad2defed3d51621b88870a7..4103cc92d345b8af6e62ecc152ea91b4810e70b5 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/share/PhysDESDM_KinkedTrack.py +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/share/PhysDESDM_KinkedTrack.py @@ -33,9 +33,6 @@ def KinkTrkTriggerFilterString(flags): return selectionString - - - #==================================================================== # JetMetFilter #==================================================================== diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkSingleJetMetFilterTool.cxx b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkSingleJetMetFilterTool.cxx index 03d0ceb3f535d4bd80302ed5b53c72d8146d90a5..ecb7aed4ec54f19146df3a9ec1bc4a412baf5ee4 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkSingleJetMetFilterTool.cxx +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkSingleJetMetFilterTool.cxx @@ -25,6 +25,7 @@ DerivationFramework::KinkTrkSingleJetMetFilterTool::KinkTrkSingleJetMetFilterToo AthAlgTool(t,n,p), m_ntot(0), m_npass(0), + m_muonSelectionTool("CP::MuonSelectionTool/MuonSelectionTool"), m_passAll(false), m_LeptonVeto(false), m_isolatedTrack(false), @@ -32,11 +33,10 @@ DerivationFramework::KinkTrkSingleJetMetFilterTool::KinkTrkSingleJetMetFilterToo m_jetSGKey("AntiKt4LCTopoJets"), m_metSGKey("MET_RefFinal"), m_metTerm("Final"), - m_muonSelectionTool("CP::MuonSelectionTool/MuonSelectionTool"), m_muonSGKey("Muons"), m_muonIDKey("Medium"), m_electronSGKey("ElectronCollection"), - m_electronIDKey("Tight"), + m_electronIDKey("LHTight"), m_metCut(-1), m_jetPtCuts(std::vector<float>()), m_jetEtaMax(3.2), @@ -78,6 +78,7 @@ StatusCode DerivationFramework::KinkTrkSingleJetMetFilterTool::initialize() { ATH_MSG_VERBOSE("initialize() ..."); + // Muon selection CHECK(m_muonSelectionTool.retrieve()); return StatusCode::SUCCESS; @@ -170,26 +171,10 @@ bool DerivationFramework::KinkTrkSingleJetMetFilterTool::eventPassesFilter() con // Retrieve muon container const xAOD::MuonContainer* muons(0); ATH_CHECK( evtStore()->retrieve(muons, m_muonSGKey) ); - int qflag(0); - if (m_muonIDKey == "VeryLoose") { - qflag = xAOD::Muon::VeryLoose; - } else if (m_muonIDKey == "Loose") { - qflag = xAOD::Muon::Loose; - } else if (m_muonIDKey == "Medium") { - qflag = xAOD::Muon::Medium; - } else if (m_muonIDKey == "Tight") { - qflag = xAOD::Muon::Tight; - } else { - ATH_MSG_WARNING("Cannot find the muon quality flag " << m_muonIDKey << ". Use Medium instead."); - qflag = xAOD::Muon::Medium; - } - for (auto muon: *muons) { - bool passID(false); - if (m_muonSelectionTool->getQuality(*muon) <= qflag) { - passID = true; - } - if (muon->pt() > m_leptonPtCut && fabs(muon->eta()) < m_leptonEtaMax && passID) { + if( !m_muonSelectionTool->passedMuonCuts(*muon) ) continue; + if( muon->muonType() != xAOD::Muon::Combined ) continue; + if(muon->pt() > m_leptonPtCut && fabs(muon->eta()) < m_leptonEtaMax ) { return acceptEvent; } } @@ -199,8 +184,8 @@ bool DerivationFramework::KinkTrkSingleJetMetFilterTool::eventPassesFilter() con ATH_CHECK(evtStore()->retrieve(electrons, m_electronSGKey)); for (auto ele: *electrons) { bool passID(false); - if (!ele->passSelection(passID, m_electronIDKey)) { - ATH_MSG_WARNING("Cannot find the electron quality flag " << m_muonIDKey); + if( !ele->passSelection(passID,m_electronIDKey) ){ + ATH_MSG_WARNING("Cannot find the electron quality flag " << m_electronIDKey); } if (ele->pt() > m_leptonPtCut && fabs(ele->eta()) < m_leptonEtaMax && passID) { return acceptEvent; @@ -210,13 +195,27 @@ bool DerivationFramework::KinkTrkSingleJetMetFilterTool::eventPassesFilter() con // at least 1 isolated pixel tracklet OR standard track if(m_isolatedTrack){ - //if(true){ + // Find IsolatedTracklet - bool passIsolatedTracklet = false; const xAOD::TrackParticleContainer *pixelTrackletContainer=NULL; ATH_CHECK( evtStore()->retrieve(pixelTrackletContainer, "InDetPixelPrdAssociationTrackParticles") ); - - for(auto Tracklet : *pixelTrackletContainer){ + + const xAOD::VertexContainer* vertices(0); + ATH_CHECK( evtStore()->retrieve(vertices, "PrimaryVertices") ); + const xAOD::Vertex* pv = 0; + for( const auto& v: *vertices ){ + if( v->vertexType() == xAOD::VxType::PriVtx ){ + pv = v; + break; + } + } + if( !pv ){ + ATH_MSG_WARNING("Cannot find a PV in the event; reject it!"); + return false; + } + + bool passIsolatedTracklet = false; + for(const auto& Tracklet : *pixelTrackletContainer){ passIsolatedTracklet = true; for(unsigned int i=0;i<goodJets.size();i++){ double deltaPhi = (fabs(Tracklet->phi() - goodJets.at(i)->phi()) > M_PI) ? 2.0*M_PI-fabs(Tracklet->phi()-goodJets.at(i)->phi()) : fabs(Tracklet->phi()-goodJets.at(i)->phi()); @@ -231,6 +230,11 @@ bool DerivationFramework::KinkTrkSingleJetMetFilterTool::eventPassesFilter() con if(passIsolatedTracklet==false) continue; + + if( Tracklet->pt() < 20000.0 ){ + passIsolatedTracklet = false; + continue; + } if(TMath::Abs(Tracklet->eta()) < 0.1 || TMath::Abs(Tracklet->eta()) > 1.9){ passIsolatedTracklet = false; @@ -242,7 +246,7 @@ bool DerivationFramework::KinkTrkSingleJetMetFilterTool::eventPassesFilter() con continue; } - if(Tracklet->auxdata<UChar_t>("numberOfContribPixelLayers")<4){ + if(Tracklet->auxdata<UChar_t>("numberOfContribPixelLayers")<3){ passIsolatedTracklet = false; continue; } @@ -251,8 +255,16 @@ bool DerivationFramework::KinkTrkSingleJetMetFilterTool::eventPassesFilter() con passIsolatedTracklet = false; continue; } + + double z0SinTheta = (Tracklet->z0() + Tracklet->vz() - pv->z() ) * TMath::Sin(Tracklet->p4().Theta()); + if( fabs(z0SinTheta) > 5.0 ){ + passIsolatedTracklet = false; + continue; + } + if(passIsolatedTracklet) break; + }// for Tracklet if(passIsolatedTracklet==false){ @@ -262,7 +274,7 @@ bool DerivationFramework::KinkTrkSingleJetMetFilterTool::eventPassesFilter() con const xAOD::TrackParticleContainer *standardTrackContainer=NULL; ATH_CHECK( evtStore()->retrieve(standardTrackContainer, "InDetTrackParticles") ); - for(auto StdTrack : *standardTrackContainer){ + for(const auto& StdTrack : *standardTrackContainer){ if(StdTrack->pt()/1000.0 < 20.0) continue; diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkZeeTagTool.cxx b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkZeeTagTool.cxx index 44988ef6ca1de73702a2e60dcd05be9598390d10..ddcf1ebb463064974b0b6b4bf04d46442767088d 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkZeeTagTool.cxx +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkZeeTagTool.cxx @@ -176,8 +176,8 @@ bool DerivationFramework::KinkTrkZeeTagTool::checkEleClusPair(const xAOD::Electr bool DerivationFramework::KinkTrkZeeTagTool::passElectronQuality(const xAOD::Electron *ele) const { - if (ele->pt() < m_electronPtCut) return false; - if (fabs(ele->eta()) > m_electronEtaMax) return false; + if( ele->pt() < m_electronPtCut ) return false; + if( fabs(ele->eta()) > m_electronEtaMax ) return false; bool passID(false); for (unsigned int i=0; i<m_electronIDKeys.size(); i++) { if (ele->passSelection(passID, m_electronIDKeys[i])) { @@ -187,6 +187,7 @@ bool DerivationFramework::KinkTrkZeeTagTool::passElectronQuality(const xAOD::Ele } } if (!passID) return false; + return true; } diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkZmumuTagTool.cxx b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkZmumuTagTool.cxx index b6cc0a3909aff952b36ab1eec054564b730bd43d..8c1ddf647a7ac70390355779c960a8cdadfeb30d 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkZmumuTagTool.cxx +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/KinkTrkZmumuTagTool.cxx @@ -184,32 +184,12 @@ bool DerivationFramework::KinkTrkZmumuTagTool::checkMuonTrackPair(const xAOD::Mu bool DerivationFramework::KinkTrkZmumuTagTool::passMuonQuality(const xAOD::Muon *muon) const { - if (muon->pt() < m_muonPtCut) return false; - if (fabs(muon->eta()) > m_muonEtaMax) return false; - - bool passID(false); - for (unsigned int i=0; i<m_muonIDKeys.size(); i++) { - int qflag(0); - if (m_muonIDKeys[i] == "VeryLoose") { - qflag = xAOD::Muon::VeryLoose; - } else if (m_muonIDKeys[i] == "Loose") { - qflag = xAOD::Muon::Loose; - } else if (m_muonIDKeys[i] == "Medium" ) { - qflag = xAOD::Muon::Medium; - } else if (m_muonIDKeys[i] == "Tight") { - qflag = xAOD::Muon::Tight; - } else { - ATH_MSG_WARNING("Cannot find the muon quality flag " << m_muonIDKeys[i] << ". Use Medium instead."); - qflag = xAOD::Muon::Medium; - } - - if ( m_muonSelectionTool->getQuality(*muon) <= qflag ) { - passID = true; - break; - } - } - if (!passID) return false; + if( muon->pt() < m_muonPtCut ) return false; + if( fabs(muon->eta()) > m_muonEtaMax ) return false; + if( !m_muonSelectionTool->passedMuonCuts(*muon) ) return false; + if( muon->muonType() != xAOD::Muon::Combined ) return false; + // Good muon! return true; } diff --git a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/VHLowTrackJetFilterTool.cxx b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/VHLowTrackJetFilterTool.cxx index 81f81036e8caf3dd89d8b9758a0f23ee808a92de..bd4600238aa5ec9ddb5a53207b1fab3f19b20ac7 100644 --- a/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/VHLowTrackJetFilterTool.cxx +++ b/PhysicsAnalysis/SUSYPhys/LongLivedParticleDPDMaker/src/VHLowTrackJetFilterTool.cxx @@ -7,7 +7,6 @@ /////////////////////////////////////////////////////////////////// #include "LongLivedParticleDPDMaker/VHLowTrackJetFilterTool.h" - #include "xAODEgamma/ElectronContainer.h" #include "xAODEventInfo/EventInfo.h" #include "xAODJet/JetContainer.h" @@ -41,7 +40,7 @@ m_AlphaMaxCut(0.03), m_CHFCut(0.3), m_nJetsReq(0), m_electronSGKey("Electrons"), -m_electronIDKey("Medium"), +m_electronIDKey("LHMedium"), m_electronPtCut(0), m_muonSelectionTool("CP::MuonSelectionTool/MuonSelectionTool"), m_muonSGKey("Muons"), @@ -74,7 +73,6 @@ m_muonPtCut(0) } // Athena finalize - StatusCode DerivationFramework::VHLowTrackJetFilterTool::finalize() { ATH_MSG_VERBOSE("finalize() ..."); @@ -92,7 +90,6 @@ StatusCode DerivationFramework::VHLowTrackJetFilterTool::finalize() // The filter itself bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const { - typedef std::vector<const xAOD::TrackParticle*> Particles; typedef ElementLink<xAOD::TrackParticleContainer> TrackLink; typedef std::vector<TrackLink> TrackLinks; @@ -115,7 +112,8 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + //electron portion const xAOD::ElectronContainer* electrons(0); sc = evtStore()->retrieve(electrons,m_electronSGKey); @@ -124,12 +122,14 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const return false; } + // loop over the electrons in the container for (auto electron : *electrons){ - + if(electron->pt()<m_electronPtCut) continue; if( (fabs(electron->caloCluster()->etaBE(2))>1.37 && fabs(electron->caloCluster()->etaBE(2)<1.52)) || fabs(electron->caloCluster()->etaBE(2))>2.47 ) continue; + if(electron->isolation(xAOD::Iso::topoetcone20)/electron->pt()>0.2) continue; bool passID=false; @@ -147,7 +147,7 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const double delta_z0 = tp->z0() + tp->vz() - vertex->z(); double theta = tp->theta(); float z0sintheta = fabs(delta_z0 * sin(theta)); - + if (sigd0>5) continue; if (z0sintheta>0.5) continue; @@ -155,6 +155,7 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const break; } } + if (passesEl){ m_nEventsPassElectron++; break; @@ -165,31 +166,21 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //muon portion - int qflag=0; - if (m_muonIDKey == "VeryLoose") { - qflag = xAOD::Muon::VeryLoose; - } else if (m_muonIDKey == "Loose") { - qflag = xAOD::Muon::Loose; - } else if (m_muonIDKey == "Medium") { - qflag = xAOD::Muon::Medium; - } else if (m_muonIDKey == "Tight") { - qflag = xAOD::Muon::Tight; - } else { - ATH_MSG_FATAL("Cannot find the muon quality flag " << m_muonIDKey << "."); - return false; - } - + const xAOD::MuonContainer* muons(0); sc = evtStore()->retrieve(muons,m_muonSGKey); if (sc.isFailure()) { ATH_MSG_FATAL("No muon collection with name " << m_muonSGKey << " found in StoreGate!"); return false; } + for(auto muon : *muons){ + if (muon->pt()<m_muonPtCut) continue; if (fabs(muon->eta())>2.5) continue; - if (!(m_muonSelectionTool->getQuality(*muon) <= qflag)) continue; + if (!(m_muonSelectionTool->passedMuonCuts(*muon))) continue; + if (muon->muonType()!=xAOD::Muon::Combined) continue; if (muon->isolation(xAOD::Iso::topoetcone20)/muon->pt()>0.3) continue; for (auto vertex : *vertices) { // Select good primary vertex @@ -197,17 +188,20 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const const xAOD::TrackParticle* tp = muon->primaryTrackParticle() ; //your input track particle from the electron double d0sig = xAOD::TrackingHelpers::d0significance( tp, eventInfo->beamPosSigmaX(), eventInfo->beamPosSigmaY(), eventInfo->beamPosSigmaXY() ); + if (fabs(d0sig)>3) continue; float delta_z0 = tp->z0() + tp->vz() - vertex->z(); float theta = tp->theta(); double z0sintheta = delta_z0 * sin(theta); + if (fabs(z0sintheta)>0.5) continue; - + passesMu = true; break; } } + if (passesMu) { m_nEventsPassMuon++; break; @@ -228,18 +222,37 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const std::vector<const xAOD::Jet*> goodJets; for (auto jet : *jets) { + + if (jet->pt() < m_jetPtCut) continue; + if (fabs(jet->eta()) > m_jetEtaCut) continue; + TLorentzVector VJet = TLorentzVector(0.0,0.0,0.0,0.0); VJet.SetPtEtaPhiE(jet->pt(), jet->eta(), jet->phi(), jet->e()); - + float minDeltaR = 100; + for (auto electron : *electrons ){ - if (!electron->passSelection("Loose")) continue; + + if (electron->pt()<20000) continue; + if (fabs(electron->eta())>2.47) continue; + + bool passLoose=false; + if (!electron->passSelection(passLoose, "LHLoose")){ + ATH_MSG_WARNING("Cannot find the LHLoose electron quality flag"); + continue; + } + if (!passLoose) continue; + TLorentzVector VElec=electron->p4(); float deltaR = VJet.DeltaR(VElec); + if (deltaR<minDeltaR) minDeltaR=deltaR; } + if (minDeltaR<0.2) continue; + goodJets.push_back(jet); + } @@ -248,9 +261,6 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const jetNo++; if (jetNo>=3) break; //Only consider two leading jets - if (jet->pt() < m_jetPtCut) continue; - if (fabs(jet->eta()) > m_jetEtaCut) continue; - TLorentzVector CHFNum = TLorentzVector(0.0,0.0,0.0,0.0); const xAOD::BTagging *bjet(nullptr); bjet = jet->btagging(); @@ -274,7 +284,7 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const TLorentzVector VTrack = TLorentzVector(0.0,0.0,0.0,0.0); VTrack.SetPtEtaPhiE(track->pt(),track->eta(), track->phi(), track->e()); alphaDen=alphaDen+VTrack; - if (track->d0() > m_TrackD0Max) continue; + if (fabs(track->d0()) > m_TrackD0Max) continue; float z0 = track->z0() + track->vz() - vertex->z(); float theta = track->theta(); @@ -291,19 +301,23 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const CHFNum = TLorentzVector(0.0,0.0,0.0,0.0); for(auto track : goodTracks) { if (track->pt() < m_TrackMinPt) continue; - if (track->d0() > m_TrackD0Max) continue; + if (fabs(track->d0()) > m_TrackD0Max) continue; TLorentzVector VTrack = TLorentzVector(0.0,0.0,0.0,0.0); VTrack.SetPtEtaPhiE(track->pt(),track->eta(), track->phi(), track->e()); CHFNum=CHFNum+VTrack; + } + float chf = CHFNum.Pt()/jet->pt(); if (alpha_max < m_AlphaMaxCut) m_nJetsPassAlphaMax++; if (chf < m_CHFCut) m_nJetsPassCHF++; if (chf > m_CHFCut && alpha_max > m_AlphaMaxCut) continue; + nJetsPassed++; + } if (nJetsPassed >= m_nJetsReq){ @@ -312,7 +326,7 @@ bool DerivationFramework::VHLowTrackJetFilterTool::eventPassesFilter() const } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + if (passesJet && (passesEl || passesMu)){ m_nEventsPass++; return true; diff --git a/Reconstruction/RecExample/RecExCommon/share/RecExCommon_topOptions.py b/Reconstruction/RecExample/RecExCommon/share/RecExCommon_topOptions.py index d8408fb750c2cb1fad3d653078ba56c872fb5d7a..121783b1ce01957117506c182e33340916a04566 100755 --- a/Reconstruction/RecExample/RecExCommon/share/RecExCommon_topOptions.py +++ b/Reconstruction/RecExample/RecExCommon/share/RecExCommon_topOptions.py @@ -1106,13 +1106,14 @@ if rec.doFileMetaData(): ###=== Only run reco on events that pass selected triggers ##-------------------------------------------------------- if rec.doTrigger and rec.doTriggerFilter() and globalflags.DataSource() == 'data' and globalflags.InputFormat == 'bytestream': + logRecExCommon_topOptions.info('Setting up trigger filtering') try: ### seq will be our filter sequence from AthenaCommon.AlgSequence import AthSequencer seq=AthSequencer("AthFilterSeq") seq+=CfgMgr.EventCounterAlg("AllExecutedEventsAthFilterSeq") seq+=topSequence.TrigConfDataIOVChanger - seq+=topSequence.RoIBResultToAOD + seq+=topSequence.RoIBResultToxAOD seq+=topSequence.TrigBSExtraction seq+=topSequence.TrigDecMaker @@ -1120,9 +1121,9 @@ if rec.doTrigger and rec.doTriggerFilter() and globalflags.DataSource() == 'data seq += TriggerSelectorAlg('TriggerAlg1') seq.TriggerAlg1.TriggerSelection = rec.triggerFilterList() pass - except: + except Exception, e: + logRecExCommon_topOptions.error('Trigger filtering not set up, reason: ' + `e`) pass - pass ##-------------------------------------------------------- diff --git a/Reconstruction/RecJobTransforms/share/skeleton.RAWtoALL_tf.py b/Reconstruction/RecJobTransforms/share/skeleton.RAWtoALL_tf.py index a33f1f71daec30b8353fa25bd6944fcafaedc47c..7aab49cfa5b4e936901c57d0665e64eb72edfad0 100644 --- a/Reconstruction/RecJobTransforms/share/skeleton.RAWtoALL_tf.py +++ b/Reconstruction/RecJobTransforms/share/skeleton.RAWtoALL_tf.py @@ -49,7 +49,7 @@ if hasattr(runArgs,"inputEVNTFile"): ## Output if hasattr(runArgs,"trigFilterList"): rec.doTriggerFilter.set_Value_and_Lock(True) - rec.triggerFilterList = "|".join(runArgs.trigFilterList) + rec.triggerFilterList = "||".join(runArgs.trigFilterList) if hasattr(runArgs,"outputESDFile"): rec.doESD.set_Value_and_Lock( True ) diff --git a/Reconstruction/RecJobTransforms/share/skeleton.RAWtoESD_tf.py b/Reconstruction/RecJobTransforms/share/skeleton.RAWtoESD_tf.py index 6b382d41b834067625f687bff18f4af486c0438f..36e8f5e19f5d2d071c56ea8d01b941c1e12e67c4 100644 --- a/Reconstruction/RecJobTransforms/share/skeleton.RAWtoESD_tf.py +++ b/Reconstruction/RecJobTransforms/share/skeleton.RAWtoESD_tf.py @@ -121,7 +121,7 @@ if hasattr(runArgs,"outputDRAW_WMUNUFile"): if hasattr(runArgs,"trigFilterList"): rec.doTriggerFilter.set_Value_and_Lock(True) - rec.triggerFilterList = "|".join(runArgs.trigFilterList) + rec.triggerFilterList = "||".join(runArgs.trigFilterList) if hasattr(runArgs,"outputESDFile"): rec.doESD.set_Value_and_Lock( True ) diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/VrtSecInclusive.h b/Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/VrtSecInclusive.h index dddd4ca71265e6cbcdb7fd3e8956ce791e98ff49..0e785d28934f464f31071462c89450b92d543c02 100755 --- a/Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/VrtSecInclusive.h +++ b/Reconstruction/VKalVrt/VrtSecInclusive/VrtSecInclusive/VrtSecInclusive.h @@ -165,6 +165,9 @@ namespace VKalVrtAthena { int CutTRTHits; // Kazuki int CutTightSCTHits; int CutTightTRTHits; + + /* track extrpolator; 1==VKalGetImpact, 2==m_trackToVertexTool*/ + int trkExtrapolator; // Vertex reconstruction bool doPVcompatibilityCut; @@ -198,7 +201,7 @@ namespace VKalVrtAthena { double mergeByShufflingAllowance; double improveChi2ProbThreshold; - + // vertexing using muons (test implementation) bool doSelectTracksFromMuons; bool doSelectTracksFromElectrons; @@ -384,6 +387,12 @@ namespace VKalVrtAthena { /** finalization of the vertex and store to xAOD::VertexContainer */ StatusCode refitAndSelectGoodQualityVertices( std::vector<WrkVrt>* ); + + /** get secondary vertex impact parameters **/ + bool getSVImpactParameters(const xAOD::TrackParticle* trk, Amg::Vector3D vertex, std::vector<double>& impactParameters, std::vector<double>& impactParErrors); + + enum TrkParameter { k_d0=0, k_z0=1, k_theta=2, k_phi=3, k_qOverP=4 ,k_nTP=5 }; + enum TrkParameterUnc { k_d0d0=0, k_z0z0=1, k_nTPU=2 }; using vertexingAlg = StatusCode (VrtSecInclusive::*)( std::vector<WrkVrt>* ); std::vector< std::pair<std::string, vertexingAlg> > m_vertexingAlgorithms; diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/src/Utilities.cxx b/Reconstruction/VKalVrt/VrtSecInclusive/src/Utilities.cxx index c32ede1a1141264898902dfdcbccf53159675707..c3997da004d35c159ab6d99a6c006a53aaa0c09f 100644 --- a/Reconstruction/VKalVrt/VrtSecInclusive/src/Utilities.cxx +++ b/Reconstruction/VKalVrt/VrtSecInclusive/src/Utilities.cxx @@ -726,6 +726,8 @@ namespace VKalVrtAthena { declareProperty("CutTRTHits", m_jp.CutTRTHits = 0 ); declareProperty("CutTightSCTHits", m_jp.CutTightSCTHits = 7 ); declareProperty("CutTightTRTHits", m_jp.CutTightTRTHits = 20 ); + + declareProperty("TrkExtrapolator", m_jp.trkExtrapolator = 2 ); declareProperty("doReassembleVertices", m_jp.doReassembleVertices = false ); declareProperty("doMergeByShuffling", m_jp.doMergeByShuffling = false ); diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/src/VertexingAlgs.cxx b/Reconstruction/VKalVrt/VrtSecInclusive/src/VertexingAlgs.cxx index 15072afd0a800bb04195bc77f1aad7085266de5d..b8f337a07cb5b15c513bc4cabdf61764c90908bb 100644 --- a/Reconstruction/VKalVrt/VrtSecInclusive/src/VertexingAlgs.cxx +++ b/Reconstruction/VKalVrt/VrtSecInclusive/src/VertexingAlgs.cxx @@ -113,15 +113,16 @@ namespace VKalVrtAthena { std::vector<double> impactParameters; std::vector<double> impactParErrors; - m_fitSvc->VKalGetImpact( *itrk, initVertex, static_cast<long int>( (*itrk)->charge() ), impactParameters, impactParErrors); - const auto roughD0_itrk = impactParameters.at(0); - const auto roughZ0_itrk = impactParameters.at(1); - if( fabs( impactParameters.at(0) ) > roughD0Cut || fabs( impactParameters.at(1) ) > roughZ0Cut ) { + if( !getSVImpactParameters( *itrk, initVertex, impactParameters, impactParErrors) ) continue; + const auto roughD0_itrk = impactParameters.at(TrkParameter::k_d0); + const auto roughZ0_itrk = impactParameters.at(TrkParameter::k_z0); + if( fabs( impactParameters.at(0)) > roughD0Cut || fabs( impactParameters.at(1) ) > roughZ0Cut ) { continue; } - m_fitSvc->VKalGetImpact( *jtrk, initVertex, static_cast<long int>( (*jtrk)->charge() ), impactParameters, impactParErrors); - const auto roughD0_jtrk = impactParameters.at(0); - const auto roughZ0_jtrk = impactParameters.at(1); + + if( !getSVImpactParameters( *jtrk, initVertex, impactParameters, impactParErrors) ) continue; + const auto roughD0_jtrk = impactParameters.at(TrkParameter::k_d0); + const auto roughZ0_jtrk = impactParameters.at(TrkParameter::k_z0); if( fabs( impactParameters.at(0) ) > roughD0Cut || fabs( impactParameters.at(1) ) > roughZ0Cut ) { continue; } @@ -944,15 +945,13 @@ namespace VKalVrtAthena { std::vector<double> impactParameters; std::vector<double> impactParErrors; - m_fitSvc->VKalGetImpact(trk, targetVertex.vertex, static_cast<int>( trk->charge() ), impactParameters, impactParErrors); - - enum { k_d0, k_z0, k_theta, k_phi, k_qOverP }; - - const auto& distance = hypot( impactParameters.at(k_d0), impactParameters.at(k_z0) ); + if( !getSVImpactParameters(trk,targetVertex.vertex,impactParameters,impactParErrors) ) continue; + + const auto& distance = hypot( impactParameters.at(0), impactParameters.at(1) ); distances.emplace_back( distance ); - if( fabs( impactParameters.at(k_d0) > m_jp.reassembleMaxImpactParameterD0 ) ) continue; - if( fabs( impactParameters.at(k_z0) > m_jp.reassembleMaxImpactParameterZ0 ) ) continue; + if( fabs( impactParameters.at(0) ) > m_jp.reassembleMaxImpactParameterD0 ) continue; + if( fabs( impactParameters.at(1) ) > m_jp.reassembleMaxImpactParameterZ0 ) continue; mergiableVertex[index] = ritr; mergiableVerticesSet.emplace( ritr ); @@ -1097,13 +1096,10 @@ namespace VKalVrtAthena { std::vector<double> impactParameters; std::vector<double> impactParErrors; - m_fitSvc->VKalGetImpact(trk, vertexPos, static_cast<int>( trk->charge() ), impactParameters, impactParErrors); - - enum { k_d0, k_z0, k_theta, k_phi, k_qOverP }; - enum { k_d0d0, k_d0z0, k_z0z0 }; - - if( fabs( impactParameters.at(k_d0) ) / sqrt( impactParErrors.at(k_d0d0) ) > m_jp.associateMaxD0Signif ) continue; - if( fabs( impactParameters.at(k_z0) ) / sqrt( impactParErrors.at(k_z0z0) ) > m_jp.associateMaxZ0Signif ) continue; + if( !getSVImpactParameters( trk, vertexPos, impactParameters, impactParErrors) ) continue; + + if( fabs( impactParameters.at(0) ) / sqrt( impactParErrors.at(0) ) > m_jp.associateMaxD0Signif ) continue; + if( fabs( impactParameters.at(1) ) / sqrt( impactParErrors.at(1) ) > m_jp.associateMaxZ0Signif ) continue; ATH_MSG_DEBUG( " > " << __FUNCTION__ << ": trk " << trk << ": d0 to vtx = " << impactParameters.at(k_d0) @@ -1987,5 +1983,35 @@ namespace VKalVrtAthena { return StatusCode::SUCCESS; } + //____________________________________________________________________________________________________ + bool VrtSecInclusive::getSVImpactParameters(const xAOD::TrackParticle* trk, Amg::Vector3D vertex, + std::vector<double>& impactParameters, + std::vector<double>& impactParErrors){ + + impactParameters.clear(); + impactParErrors.clear(); + + if( m_jp.trkExtrapolator==1 ){ + m_fitSvc->VKalGetImpact(trk, vertex, static_cast<int>( trk->charge() ), impactParameters, impactParErrors); + } + else if( m_jp.trkExtrapolator==2 ){ + const Trk::Perigee* sv_perigee = m_trackToVertexTool->perigeeAtVertex( *trk, vertex ); + if( !sv_perigee ) return false; + impactParameters.push_back(sv_perigee->parameters() [Trk::d0]); + impactParameters.push_back(sv_perigee->parameters() [Trk::z0]); + impactParErrors.push_back((*sv_perigee->covariance())( Trk::d0, Trk::d0 )); + impactParErrors.push_back((*sv_perigee->covariance())( Trk::z0, Trk::z0 )); + delete sv_perigee; + } + else{ + ATH_MSG_WARNING( " > " << __FUNCTION__ << ": Unknown track extrapolator " << m_jp.trkExtrapolator ); + return false; + } + + return true; + + } // getSVImpactParameters + + } // end of namespace VKalVrtAthena diff --git a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.cxx b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.cxx index 2a18a7247dc0fa4e312bb5ae0384d94c9f12fcda..054404ed4fdae5b0243de81a630b198691917532 100644 --- a/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.cxx +++ b/Simulation/G4Utilities/MCTruthSimAlgs/src/MergeHijingParsTool.cxx @@ -39,7 +39,7 @@ StatusCode MergeHijingParsTool::processBunchXing(int, SubEventIterator iEvt = bSubEvents; for (; iEvt!=eSubEvents; iEvt++) { - StoreGateSvc& seStore(*bSubEvents->ptr()->evtStore()); + StoreGateSvc& seStore(*iEvt->ptr()->evtStore()); if (seStore.contains<HijingEventParams>(m_outputObject.name())) { const HijingEventParams *hijing_pars(nullptr); diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/CMakeLists.txt b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/CMakeLists.txt index 0ae7cd4c62957f2f2d2c0c77107df897482adcbc..8987393052a7cab80a8cf6373dc5928f6427f9e2 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/CMakeLists.txt +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/CMakeLists.txt @@ -36,9 +36,13 @@ atlas_add_root_dictionary( ISF_FastCaloSimEvent _dictSource ISF_FastCaloSimEvent/TFCS1DFunctionRegression.h ISF_FastCaloSimEvent/TFCS1DFunctionRegressionTF.h ISF_FastCaloSimEvent/TFCS1DFunctionSpline.h + ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHelpers.h ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHistogram.h + ISF_FastCaloSimEvent/TFCS1DFunctionTemplateInterpolationHistogram.h ISF_FastCaloSimEvent/TFCS2DFunction.h ISF_FastCaloSimEvent/TFCS2DFunctionHistogram.h + ISF_FastCaloSimEvent/TFCS2DFunctionTemplateHistogram.h + ISF_FastCaloSimEvent/TFCS2DFunctionTemplateInterpolationHistogram.h ISF_FastCaloSimEvent/TFCSParametrizationBase.h ISF_FastCaloSimEvent/TFCSParametrizationPlaceholder.h ISF_FastCaloSimEvent/TFCSParametrization.h @@ -61,13 +65,18 @@ atlas_add_root_dictionary( ISF_FastCaloSimEvent _dictSource ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h ISF_FastCaloSimEvent/TFCSCenterPositionCalculation.h + ISF_FastCaloSimEvent/TFCSFlatLateralShapeParametrization.h ISF_FastCaloSimEvent/TFCSHistoLateralShapeParametrization.h ISF_FastCaloSimEvent/TFCSHistoLateralShapeParametrizationFCal.h + ISF_FastCaloSimEvent/TFCS2DFunctionLateralShapeParametrization.h + ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeight.h + ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeightHitAndMiss.h ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitNumberFromE.h ISF_FastCaloSimEvent/TFCSHitCellMapping.h ISF_FastCaloSimEvent/TFCSHitCellMappingFCal.h ISF_FastCaloSimEvent/TFCSHitCellMappingWiggle.h ISF_FastCaloSimEvent/TFCSHitCellMappingWiggleEMB.h + ISF_FastCaloSimEvent/TFCSEnergyRenormalization.h ISF_FastCaloSimEvent/TFCSExtrapolationState.h ISF_FastCaloSimEvent/TFCSSimulationState.h ISF_FastCaloSimEvent/TFCSTruthState.h diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/LinkDef.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/LinkDef.h index ffce63d8d40aac7be68aa41367d975c00201c813..cf6a205e893629cdbe3b52ac82dd201104e99580 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/LinkDef.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/LinkDef.h @@ -12,9 +12,13 @@ #include "ISF_FastCaloSimEvent/TFCS1DFunctionRegression.h" #include "ISF_FastCaloSimEvent/TFCS1DFunctionRegressionTF.h" #include "ISF_FastCaloSimEvent/TFCS1DFunctionSpline.h" +#include "ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHelpers.h" #include "ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHistogram.h" +#include "ISF_FastCaloSimEvent/TFCS1DFunctionTemplateInterpolationHistogram.h" #include "ISF_FastCaloSimEvent/TFCS2DFunction.h" #include "ISF_FastCaloSimEvent/TFCS2DFunctionHistogram.h" +#include "ISF_FastCaloSimEvent/TFCS2DFunctionTemplateHistogram.h" +#include "ISF_FastCaloSimEvent/TFCS2DFunctionTemplateInterpolationHistogram.h" #include "ISF_FastCaloSimEvent/TFCSParametrizationBase.h" #include "ISF_FastCaloSimEvent/TFCSParametrizationPlaceholder.h" @@ -40,13 +44,18 @@ #include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h" #include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h" #include "ISF_FastCaloSimEvent/TFCSCenterPositionCalculation.h" +#include "ISF_FastCaloSimEvent/TFCSFlatLateralShapeParametrization.h" #include "ISF_FastCaloSimEvent/TFCSHistoLateralShapeParametrization.h" #include "ISF_FastCaloSimEvent/TFCSHistoLateralShapeParametrizationFCal.h" +#include "ISF_FastCaloSimEvent/TFCS2DFunctionLateralShapeParametrization.h" +#include "ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeight.h" +#include "ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeightHitAndMiss.h" #include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitNumberFromE.h" #include "ISF_FastCaloSimEvent/TFCSHitCellMapping.h" #include "ISF_FastCaloSimEvent/TFCSHitCellMappingFCal.h" #include "ISF_FastCaloSimEvent/TFCSHitCellMappingWiggle.h" #include "ISF_FastCaloSimEvent/TFCSHitCellMappingWiggleEMB.h" +#include "ISF_FastCaloSimEvent/TFCSEnergyRenormalization.h" #include "ISF_FastCaloSimEvent/TFCSTruthState.h" #include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h" @@ -64,7 +73,7 @@ #pragma link C++ class TFCS1DFunctionRegressionTF+; #pragma link C++ class TFCS1DFunctionSpline+; -///Linkdefs needed for template based histograms +///Linkdefs needed for common classes for template based histograms #pragma link C++ class TFCS1DFunction_Numeric<uint8_t,float>+; #pragma link C++ class TFCS1DFunction_Numeric<uint16_t,float>+; #pragma link C++ class TFCS1DFunction_Numeric<uint32_t,float>+; @@ -99,6 +108,7 @@ #pragma link C++ class TFCS1DFunction_HistogramFloatBinEdges+; #pragma link C++ class TFCS1DFunction_HistogramDoubleBinEdges+; +///Linkdefs needed for 1D template based histograms #pragma link C++ class TFCS1DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float>+; #pragma link C++ class TFCS1DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float>+; #pragma link C++ class TFCS1DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint32_t,float>+; @@ -120,6 +130,52 @@ #pragma link C++ class TFCS1DFunctionInt8Int16InterpolationHistogram+; #pragma link C++ class TFCS1DFunctionInt16Int16InterpolationHistogram+; #pragma link C++ class TFCS1DFunctionInt16Int32InterpolationHistogram+; + +///Linkdefs needed for 2D template based histograms +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint32_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint32_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint32_t,float>+; + +#pragma link C++ class TFCS2DFunctionInt8Int8Int8Histogram+; +#pragma link C++ class TFCS2DFunctionInt8Int8Int16Histogram+; +#pragma link C++ class TFCS2DFunctionInt8Int8Int32Histogram+; + +#pragma link C++ class TFCS2DFunctionInt8Int16Int8Histogram+; +#pragma link C++ class TFCS2DFunctionInt8Int16Int16Histogram+; +#pragma link C++ class TFCS2DFunctionInt8Int16Int32Histogram+; + +#pragma link C++ class TFCS2DFunctionInt16Int16Int8Histogram+; +#pragma link C++ class TFCS2DFunctionInt16Int16Int16Histogram+; +#pragma link C++ class TFCS2DFunctionInt16Int16Int32Histogram+; + +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint32_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint32_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint32_t,float>+; + +#pragma link C++ class TFCS2DFunctionInt8Int8Int8InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt8Int8Int16InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt8Int8Int32InterpolationHistogram+; + +#pragma link C++ class TFCS2DFunctionInt8Int16Int8InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt8Int16Int16InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt8Int16Int32InterpolationHistogram+; + +#pragma link C++ class TFCS2DFunctionInt16Int16Int8InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt16Int16Int16InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt16Int16Int32InterpolationHistogram+; + ///End Linkdefs needed for template based histograms #pragma link C++ class TFCS2DFunction+; @@ -148,13 +204,18 @@ #pragma link C++ class TFCSLateralShapeParametrizationHitBase+; #pragma link C++ class TFCSLateralShapeParametrizationHitChain+; #pragma link C++ class TFCSCenterPositionCalculation+; +#pragma link C++ class TFCSFlatLateralShapeParametrization+; #pragma link C++ class TFCSHistoLateralShapeParametrization+; #pragma link C++ class TFCSHistoLateralShapeParametrizationFCal+; +#pragma link C++ class TFCS2DFunctionLateralShapeParametrization+; +#pragma link C++ class TFCSHistoLateralShapeWeight+; +#pragma link C++ class TFCSHistoLateralShapeWeightHitAndMiss+; #pragma link C++ class TFCSLateralShapeParametrizationHitNumberFromE+; #pragma link C++ class TFCSHitCellMapping+; #pragma link C++ class TFCSHitCellMappingFCal+; #pragma link C++ class TFCSHitCellMappingWiggle+; #pragma link C++ class TFCSHitCellMappingWiggleEMB+; +#pragma link C++ class TFCSEnergyRenormalization+; #pragma link C++ class TFCSTruthState+; #pragma link C++ class TFCSExtrapolationState+; diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHelpers.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..9c7179dd99b9b63992c16f8bcd241e4a6c64cfeb --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHelpers.h @@ -0,0 +1,436 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ISF_FASTCALOSIMEVENT_TFCS1DFunctionTemplateHelpers_h +#define ISF_FASTCALOSIMEVENT_TFCS1DFunctionTemplateHelpers_h + +#include "TBuffer.h" + +#include <vector> +#include <cstring> +#include <algorithm> +#include <cmath> + +//For the purpose of FastCaloSim, 32bit are sufficient for bin counting +typedef uint32_t TFCS1DFunction_size_t; + +///Converter functions that does nothing for floats +template<typename T,typename Tfloat=float> class TFCS1DFunction_Numeric { +public: + static constexpr T MaxValue = 1; + static constexpr Tfloat MaxValueFloat = MaxValue; + + static inline T MaxCeilOnlyForInt(const Tfloat value) {return value;}; + static inline T ExpandToMaxRange(const Tfloat value) {return value;}; + static inline Tfloat ToNormalizedRange(const T value) {return value;}; +}; + +///Converter functions to store/retrive float numbers in integers +template<typename Tfloat> class TFCS1DFunction_Numeric<uint8_t,Tfloat> { +public: + static constexpr uint8_t MaxValue = UINT8_MAX; + static constexpr Tfloat MaxValueFloat = MaxValue; + + static inline uint8_t MaxCeilOnlyForInt(const Tfloat value) {return std::ceil(MaxValueFloat*value);}; + static inline uint8_t ExpandToMaxRange(const Tfloat value) {return value*(1+MaxValueFloat);}; + static inline Tfloat ToNormalizedRange(const uint8_t value) {return value/(1+MaxValueFloat);}; +}; + +///Converter functions to store/retrive float numbers in integers +template<typename Tfloat> class TFCS1DFunction_Numeric<uint16_t,Tfloat> { +public: + static constexpr uint16_t MaxValue = UINT16_MAX; + static constexpr Tfloat MaxValueFloat = MaxValue; + + static inline uint16_t MaxCeilOnlyForInt(const Tfloat value) {return std::ceil(MaxValueFloat*value);}; + static inline uint16_t ExpandToMaxRange(const Tfloat value) {return value*(1+MaxValueFloat);}; + static inline Tfloat ToNormalizedRange(const uint16_t value) {return value/(1+MaxValueFloat);}; +}; + +///Converter functions to store/retrive float numbers in integers +template<typename Tfloat> class TFCS1DFunction_Numeric<uint32_t,Tfloat> { +public: + static constexpr uint32_t MaxValue = UINT32_MAX; + static constexpr Tfloat MaxValueFloat = MaxValue; + + static inline uint32_t MaxCeilOnlyForInt(const Tfloat value) {return std::ceil(MaxValueFloat*value);}; + static inline uint32_t ExpandToMaxRange(const Tfloat value) {return value*(1+MaxValueFloat);}; + static inline Tfloat ToNormalizedRange(const uint32_t value) {return value/(1+MaxValueFloat);}; +}; + +template<typename T> class TFCS1DFunction_Array +{ + public: + typedef TFCS1DFunction_size_t size_t; + + TFCS1DFunction_Array() {}; + TFCS1DFunction_Array(size_t count) {resize(count);}; + ~TFCS1DFunction_Array() {if(m_content) delete[] m_content;}; + + std::size_t MemorySizeArray() const {return size()*sizeof(T);}; + std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; + + inline size_t size() const {return m_size;}; + + ///resize to given count, copying old content + void resize(size_t count) { + T* new_cont=nullptr; + if(count>0) new_cont=new T[count]; + if(m_content && new_cont) { + size_t ncopy=count; + if(size()<ncopy) ncopy=size(); + ncopy*=sizeof(T); + std::memcpy(new_cont,m_content,ncopy); + } + if(m_content) delete[] m_content; + m_size=count; + m_content=new_cont; + }; + + ///Direct data pointer + inline T* data() {return m_content;}; + inline const T* data() const {return m_content;}; + + ///Direct access operators. Values are in the range [0,TFCS1DFunction_Numeric<T>::MaxValue] + inline T& operator[]( size_t pos ) {return m_content[pos];}; + inline const T& operator[]( size_t pos ) const {return m_content[pos];}; + + ///begin() iterators + inline T* begin() {return m_content;}; + inline const T* begin() const {return m_content;}; + + ///end() iterators + inline T* end() {return m_content+size();}; + inline const T* end() const {return m_content+size();}; + + private: + T* m_content{nullptr};//! + size_t m_size{0}; + + //Use ClassDef without virtual functions. Saves 8 bytes per instance + ClassDefNV(TFCS1DFunction_Array,1) //TFCS1DFunction_Array +}; + +///Streamer method to persitify objects of type TFCS1DFunction_Array<T> +template<typename T> void TFCS1DFunction_Array<T>::Streamer(TBuffer &b) { + if (b.IsReading()) { + size_t count; + b >> count; + resize(count); + if(m_size>0) b.ReadFastArray(m_content, m_size); + } else { + b << m_size; + if(m_size>0) b.WriteFastArray(m_content, m_size); + } +} + +//Class to represent histogram content. Trandom should be a type with a floating point range [0,1] +template<typename T,typename Trandom=float> class TFCS1DFunction_HistogramContent +{ + public: + typedef TFCS1DFunction_size_t size_t; + typedef T value_type; + typedef Trandom random_type; + + TFCS1DFunction_HistogramContent(size_t nbins=0):m_array(nbins >= 1 ? nbins-1 : 0) {}; + + std::size_t MemorySizeArray() const {return m_array.MemorySizeArray();}; + std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; + + ///Set the content of bin pos to a given value, where value is in the range [0,1] + void set_fraction( size_t pos, Trandom value ) { + if(pos>=size()) return; + m_array[pos]=TFCS1DFunction_Numeric<T,Trandom>::MaxCeilOnlyForInt(value); + }; + + ///Get the cumulative content at bin pos as fraction in the range [0,1] + inline Trandom get_fraction( size_t pos ) const { + if(pos>=size()) return 1; + return m_array[pos]/TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat; + }; + + ///Get the content at bin pos as fraction in the range [0,1] + inline Trandom get_binfraction( size_t pos ) const { + if(pos==0) return m_array[pos]/TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat; + if(pos==size()) return 1-(m_array[size()-1]/TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat); + return (m_array[pos]-m_array[pos-1])/TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat; + }; + + ///set number of bins. + ///The actualy alocated size is one smaller than count, as the last bin is fixed with the range [get_fraction(size()-1,1] + void set_nbins(size_t nbins) {m_array.resize(nbins >= 1 ? nbins-1 : 0);}; + + ///return number of bins. + ///This is one larger than size, as the last bin is fixed with the range [get_fraction(size()-1,1] + inline size_t get_nbins() const {return size()+1;}; + + ///Get the matching bin for a given random value in the range [0,1). + ///A residual random number to calculate a position inside this bin is returned in residual_rnd + size_t get_bin(Trandom drnd,Trandom& residual_rnd) const { + if(drnd<=0) drnd=0; + if(drnd>=1) drnd=std::nextafter((Trandom)1.0,(Trandom)0.0); + if(size()==0) { + residual_rnd=drnd; + return 0; + } + T rnd=TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat*drnd; + auto it = std::upper_bound(m_array.begin(),m_array.end(),rnd); + + T basecont=0; + if(it!=m_array.begin()) basecont=*(it-1); + + T fullcont=TFCS1DFunction_Numeric<T,Trandom>::MaxValue; + if(it!=m_array.end()) fullcont=*it; + + T dcont=fullcont-basecont; + if(dcont>0) { + residual_rnd=((Trandom)(rnd-basecont))/dcont; + if(residual_rnd>1) residual_rnd=std::nextafter((Trandom)1.0,(Trandom)0.0); + } else { + residual_rnd=0.5; + } + + if(it==m_array.end()) return size(); + return std::distance(m_array.begin(),it); + }; + + private: + TFCS1DFunction_Array<T> m_array; + inline size_t size() const {return m_array.size();}; + + //Use ClassDef without virtual functions. Saves 8 bytes per instance + ClassDefNV(TFCS1DFunction_HistogramContent,1) //TFCS1DFunction_HistogramContent +}; + +//Class to represent histogram bin edges. Trandom should be a type with a floating point range [0,1] +template<typename T,typename Trandom=float> class TFCS1DFunction_HistogramBinEdges +{ + public: + typedef TFCS1DFunction_size_t size_t; + typedef T value_type; + typedef Trandom random_type; + + TFCS1DFunction_HistogramBinEdges(size_t nbins=0):m_array(nbins+1) {}; + ~TFCS1DFunction_HistogramBinEdges() {}; + + std::size_t MemorySizeArray() const {return m_array.MemorySizeArray();}; + std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; + + ///set number of bins + void set_nbins(size_t nbins) {m_array.resize(nbins+1);}; + + ///return number of bins + inline size_t get_nbins() const {return size()-1;}; + + ///set position of lower edge of bins + void SetBinLowEdge(size_t pos,const T& value) {m_array[pos]=value;}; + + ///get position of lower edge of bins + inline const T& GetBinLowEdge(size_t pos) const {return m_array[pos];}; + + ///get the length of a bin + inline const T GetBinLength(size_t pos) const {return GetBinLowEdge(pos+1)-GetBinLowEdge(pos);}; + + ///set and get minimum + void SetMin(const T& value) {m_array[0]=value;}; + inline const T& GetMin() const {return m_array[0];}; + + ///set and get maximum + void SetMax(const T& value) {m_array[get_nbins()]=value;}; + inline const T& GetMax() const {return m_array[get_nbins()];}; + + ///set minimum and maximum + void SetMinMax(const T& valuemin,const T& valuemax) {SetMin(valuemin);SetMax(valuemax);}; + + ///Get length of interval of all bins + inline const T Length() const {return GetMax()-GetMin();}; + + ///return linear interpolated position for bin pos. Interpolation is done with a random value in the range [0,1] + inline T position(size_t pos,const Trandom& drnd) const { + return (1-drnd)*m_array[pos] + drnd*m_array[pos+1]; + }; + + ///return interpolated position for bin pos, such that histograming the position gives a linear slope m, + ///where m is in units of the bin width for bin pos. Interpolation is done with a random value in the range [0,1] + inline T position(size_t pos,Trandom m,const Trandom& drnd) const { + if(m>2) m=2; + if(m<-2) m=-2; + Trandom x=fabs(m)>0.001 ? (0.5*std::sqrt(m*(m+8*drnd-4)+4)-1)/m+0.5 : drnd; + return (1-x)*m_array[pos] + x*m_array[pos+1]; + }; + + private: + TFCS1DFunction_Array<T> m_array; + inline size_t size() const {return m_array.size();}; + + //Use ClassDef without virtual functions. Saves 8 bytes per instance + ClassDefNV(TFCS1DFunction_HistogramBinEdges,1) //TFCS1DFunction_HistogramBinEdges +}; + +class TFCS1DFunction_HistogramFloatBinEdges: public TFCS1DFunction_HistogramBinEdges<float,float> +{ + public: + TFCS1DFunction_HistogramFloatBinEdges(size_t nbins=0):TFCS1DFunction_HistogramBinEdges<float,float>(nbins) {}; + + ClassDefNV(TFCS1DFunction_HistogramFloatBinEdges,1) //TFCS1DFunction_HistogramFloatBinEdges +}; + +class TFCS1DFunction_HistogramDoubleBinEdges: public TFCS1DFunction_HistogramBinEdges<double,double> +{ + public: + TFCS1DFunction_HistogramDoubleBinEdges(size_t nbins=0):TFCS1DFunction_HistogramBinEdges<double,double>(nbins) {}; + + ClassDefNV(TFCS1DFunction_HistogramDoubleBinEdges,1) //TFCS1DFunction_HistogramDoubleBinEdges +}; + +//Class to represent histogram bin edges, where the interval between GetMin() and GetMax() +//can be stored as a different (smaller) data type Tint +//Trandom should be a type with a floating point range [0,1] +template<typename T,typename Tint,typename Trandom=float> class TFCS1DFunction_HistogramCompactBinEdges +{ + public: + typedef TFCS1DFunction_size_t size_t; + typedef T value_type; + typedef Trandom random_type; + typedef Tint internal_storage_type; + + TFCS1DFunction_HistogramCompactBinEdges(size_t nbins=0):m_array(nbins >= 1 ? nbins-1 : 0) {}; + ~TFCS1DFunction_HistogramCompactBinEdges() {}; + + std::size_t MemorySizeArray() const {return m_array.MemorySizeArray();}; + std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; + + ///set number of bins + void set_nbins(size_t nbins) {m_array.resize(nbins >= 1 ? nbins-1 : 0);}; + + ///return number of bins + inline size_t get_nbins() const {return size()+1;}; + + ///set position of lower edge of bins. Requires GetMin() and GetMax() to be set and may not be changed! + void SetBinLowEdge(size_t pos,const T& value) { + if(pos==0) { + SetMin(value); + return; + } + if(pos>=get_nbins()) { + SetMax(value); + return; + } + m_array[pos-1]=TFCS1DFunction_Numeric<Tint,T>::ExpandToMaxRange((value-GetMin())/Length()); + }; + + ///get position of lower edge of bins. Requires GetMin() and GetMax() to be set and may not be changed! + inline const T GetBinLowEdge(size_t pos) const { + if(pos==0) return GetMin(); + if(pos>=get_nbins()) return GetMax(); + return GetMin()+Length()*TFCS1DFunction_Numeric<Tint,T>::ToNormalizedRange(m_array[pos-1]); + }; + + ///get the length of a bin + inline const T GetBinLength(size_t pos) const {return GetBinLowEdge(pos+1)-GetBinLowEdge(pos);}; + + ///set and get minimum + void SetMin(const T& value) {m_Min=value;}; + inline const T& GetMin() const {return m_Min;}; + + ///set and get maximum + void SetMax(const T& value) {m_Max=value;}; + inline const T& GetMax() const {return m_Max;}; + + ///set minimum and maximum + void SetMinMax(const T& valuemin,const T& valuemax) {SetMin(valuemin);SetMax(valuemax);}; + + ///Get length of interval of all bins + inline const T Length() const {return GetMax()-GetMin();}; + + ///return linear interpolated position for bin pos. Interpolation is done with a random value in the range [0,1] + inline T position(size_t pos,const Trandom& drnd) const { + T pos1=GetBinLowEdge(pos); + T pos2=GetBinLowEdge(pos+1); + return (1-drnd)*pos1 + drnd*pos2; + }; + + ///return interpolated position for bin pos, such that histograming the position gives a linear slope m, + ///where m is in units of the bin width for bin pos. Interpolation is done with a random value in the range [0,1] + inline T position(size_t pos,Trandom m,const Trandom& drnd) const { + if(m>2) m=2; + if(m<-2) m=-2; + Trandom x=fabs(m)>0.001 ? (0.5*std::sqrt(m*(m+8*drnd-4)+4)-1)/m+0.5 : drnd; + T pos1=GetBinLowEdge(pos); + T pos2=GetBinLowEdge(pos+1); + return (1-x)*pos1 + x*pos2; + }; + + private: + TFCS1DFunction_Array<Tint> m_array; + inline size_t size() const {return m_array.size();}; + T m_Min{0}; + T m_Max{0}; + + ClassDefNV(TFCS1DFunction_HistogramCompactBinEdges,1) //TFCS1DFunction_HistogramCompactBinEdges +}; + +class TFCS1DFunction_HistogramInt8BinEdges: public TFCS1DFunction_HistogramCompactBinEdges<float,uint8_t,float> +{ + public: + TFCS1DFunction_HistogramInt8BinEdges(size_t nbins=0):TFCS1DFunction_HistogramCompactBinEdges<float,uint8_t,float>(nbins) {}; + + ClassDefNV(TFCS1DFunction_HistogramInt8BinEdges,1) //TFCS1DFunction_HistogramInt8BinEdges +}; + +class TFCS1DFunction_HistogramInt16BinEdges: public TFCS1DFunction_HistogramCompactBinEdges<float,uint16_t,float> +{ + public: + TFCS1DFunction_HistogramInt16BinEdges(size_t nbins=0):TFCS1DFunction_HistogramCompactBinEdges<float,uint16_t,float>(nbins) {}; + + ClassDefNV(TFCS1DFunction_HistogramInt16BinEdges,1) //TFCS1DFunction_HistogramInt16BinEdges +}; + +class TFCS1DFunction_HistogramInt32BinEdges: public TFCS1DFunction_HistogramCompactBinEdges<float,uint32_t,float> +{ + public: + TFCS1DFunction_HistogramInt32BinEdges(size_t nbins=0):TFCS1DFunction_HistogramCompactBinEdges<float,uint32_t,float>(nbins) {}; + + ClassDefNV(TFCS1DFunction_HistogramInt32BinEdges,1) //TFCS1DFunction_HistogramInt32BinEdges +}; + + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCS1DFunction_Numeric<uint8_t,float>+; +#pragma link C++ class TFCS1DFunction_Numeric<uint16_t,float>+; +#pragma link C++ class TFCS1DFunction_Numeric<uint32_t,float>+; +#pragma link C++ class TFCS1DFunction_Numeric<float,float>+; +#pragma link C++ class TFCS1DFunction_Numeric<double,float>+; +#pragma link C++ class TFCS1DFunction_Numeric<double,double>+; + +#pragma link C++ class TFCS1DFunction_Array<float>-; +#pragma link C++ class TFCS1DFunction_Array<double>-; +#pragma link C++ class TFCS1DFunction_Array<uint8_t>-; +#pragma link C++ class TFCS1DFunction_Array<uint16_t>-; +#pragma link C++ class TFCS1DFunction_Array<uint32_t>-; + +#pragma link C++ class TFCS1DFunction_HistogramContent<float,float>+; +#pragma link C++ class TFCS1DFunction_HistogramContent<double,float>+; +#pragma link C++ class TFCS1DFunction_HistogramContent<double,double>+; +#pragma link C++ class TFCS1DFunction_HistogramContent<uint8_t,float>+; +#pragma link C++ class TFCS1DFunction_HistogramContent<uint16_t,float>+; +#pragma link C++ class TFCS1DFunction_HistogramContent<uint32_t,float>+; + +#pragma link C++ class TFCS1DFunction_HistogramBinEdges<float,float>+; +#pragma link C++ class TFCS1DFunction_HistogramBinEdges<double,float>+; +#pragma link C++ class TFCS1DFunction_HistogramBinEdges<double,double>+; + +#pragma link C++ class TFCS1DFunction_HistogramCompactBinEdges<float,uint8_t,float>+; +#pragma link C++ class TFCS1DFunction_HistogramCompactBinEdges<float,uint16_t,float>+; +#pragma link C++ class TFCS1DFunction_HistogramCompactBinEdges<float,uint32_t,float>+; + +#pragma link C++ class TFCS1DFunction_HistogramInt8BinEdges+; +#pragma link C++ class TFCS1DFunction_HistogramInt16BinEdges+; +#pragma link C++ class TFCS1DFunction_HistogramInt32BinEdges+; +#pragma link C++ class TFCS1DFunction_HistogramFloatBinEdges+; +#pragma link C++ class TFCS1DFunction_HistogramDoubleBinEdges+; + +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHistogram.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHistogram.h index 939f21594669f063a88979c14de6ee2c1cb75114..405fae06b479c2711abda5b0bb29fe5fcf700b91 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHistogram.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHistogram.h @@ -1,404 +1,16 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ #ifndef ISF_FASTCALOSIMEVENT_TFCS1DFunctionTemplateHistogram_h #define ISF_FASTCALOSIMEVENT_TFCS1DFunctionTemplateHistogram_h #include "ISF_FastCaloSimEvent/TFCS1DFunction.h" -#include <vector> -#include "TH1.h" -#include "TBuffer.h" -#include <cstring> -#include <algorithm> -#include <cmath> - +#include "ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHelpers.h" +#include "TH1.h" #include <iostream> -//For the purpose of FastCaloSim, 32bit are sufficient for bin counting -typedef uint32_t TFCS1DFunction_size_t; - -///Converter functions that does nothing for floats -template<typename T,typename Tfloat=float> class TFCS1DFunction_Numeric { -public: - static constexpr T MaxValue = 1; - static constexpr Tfloat MaxValueFloat = MaxValue; - - static inline T MaxCeilOnlyForInt(const Tfloat value) {return value;}; - static inline T ExpandToMaxRange(const Tfloat value) {return value;}; - static inline Tfloat ToNormalizedRange(const T value) {return value;}; -}; - -///Converter functions to store/retrive float numbers in integers -template<typename Tfloat> class TFCS1DFunction_Numeric<uint8_t,Tfloat> { -public: - static constexpr uint8_t MaxValue = UINT8_MAX; - static constexpr Tfloat MaxValueFloat = MaxValue; - - static inline uint8_t MaxCeilOnlyForInt(const Tfloat value) {return std::ceil(MaxValueFloat*value);}; - static inline uint8_t ExpandToMaxRange(const Tfloat value) {return value*(1+MaxValueFloat);}; - static inline Tfloat ToNormalizedRange(const uint8_t value) {return value/(1+MaxValueFloat);}; -}; - -///Converter functions to store/retrive float numbers in integers -template<typename Tfloat> class TFCS1DFunction_Numeric<uint16_t,Tfloat> { -public: - static constexpr uint16_t MaxValue = UINT16_MAX; - static constexpr Tfloat MaxValueFloat = MaxValue; - - static inline uint16_t MaxCeilOnlyForInt(const Tfloat value) {return std::ceil(MaxValueFloat*value);}; - static inline uint16_t ExpandToMaxRange(const Tfloat value) {return value*(1+MaxValueFloat);}; - static inline Tfloat ToNormalizedRange(const uint16_t value) {return value/(1+MaxValueFloat);}; -}; - -///Converter functions to store/retrive float numbers in integers -template<typename Tfloat> class TFCS1DFunction_Numeric<uint32_t,Tfloat> { -public: - static constexpr uint32_t MaxValue = UINT32_MAX; - static constexpr Tfloat MaxValueFloat = MaxValue; - - static inline uint32_t MaxCeilOnlyForInt(const Tfloat value) {return std::ceil(MaxValueFloat*value);}; - static inline uint32_t ExpandToMaxRange(const Tfloat value) {return value*(1+MaxValueFloat);}; - static inline Tfloat ToNormalizedRange(const uint32_t value) {return value/(1+MaxValueFloat);}; -}; - -template<typename T> class TFCS1DFunction_Array -{ - public: - typedef TFCS1DFunction_size_t size_t; - - TFCS1DFunction_Array() {}; - TFCS1DFunction_Array(size_t count) {resize(count);}; - ~TFCS1DFunction_Array() {if(m_content) delete[] m_content;}; - - std::size_t MemorySizeArray() const {return size()*sizeof(T);}; - std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; - - inline size_t size() const {return m_size;}; - - ///resize to given count, copying old content - void resize(size_t count) { - T* new_cont=nullptr; - if(count>0) new_cont=new T[count]; - if(m_content && new_cont) { - size_t ncopy=count; - if(size()<ncopy) ncopy=size(); - ncopy*=sizeof(T); - std::memcpy(new_cont,m_content,ncopy); - } - if(m_content) delete[] m_content; - m_size=count; - m_content=new_cont; - }; - - ///Direct data pointer - inline T* data() {return m_content;}; - inline const T* data() const {return m_content;}; - - ///Direct access operators. Values are in the range [0,TFCS1DFunction_Numeric<T>::MaxValue] - inline T& operator[]( size_t pos ) {return m_content[pos];}; - inline const T& operator[]( size_t pos ) const {return m_content[pos];}; - - ///begin() iterators - inline T* begin() {return m_content;}; - inline const T* begin() const {return m_content;}; - - ///end() iterators - inline T* end() {return m_content+size();}; - inline const T* end() const {return m_content+size();}; - - private: - T* m_content{nullptr};//! - size_t m_size{0}; - - //Use ClassDef without virtual functions. Saves 8 bytes per instance - ClassDefNV(TFCS1DFunction_Array,1) //TFCS1DFunction_Array -}; - -///Streamer method to persitify objects of type TFCS1DFunction_Array<T> -template<typename T> void TFCS1DFunction_Array<T>::Streamer(TBuffer &b) { - if (b.IsReading()) { - size_t count; - b >> count; - resize(count); - if(m_size>0) b.ReadFastArray(m_content, m_size); - } else { - b << m_size; - if(m_size>0) b.WriteFastArray(m_content, m_size); - } -} - - -//Class to represent histogram content. Trandom should be a type with a floating point range [0,1] -template<typename T,typename Trandom=float> class TFCS1DFunction_HistogramContent -{ - public: - typedef TFCS1DFunction_size_t size_t; - typedef T value_type; - typedef Trandom random_type; - - TFCS1DFunction_HistogramContent(size_t nbins=0):m_array(nbins >= 1 ? nbins-1 : 0) {}; - - std::size_t MemorySizeArray() const {return m_array.MemorySizeArray();}; - std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; - - ///Set the content of bin pos to a given value, where value is in the range [0,1] - void set_fraction( size_t pos, Trandom value ) { - if(pos>=size()) return; - m_array[pos]=TFCS1DFunction_Numeric<T,Trandom>::MaxCeilOnlyForInt(value); - }; - - ///Get the cumulative content at bin pos as fraction in the range [0,1] - inline Trandom get_fraction( size_t pos ) const { - if(pos>=size()) return 1; - return m_array[pos]/TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat; - }; - - ///Get the content at bin pos as fraction in the range [0,1] - inline Trandom get_binfraction( size_t pos ) const { - if(pos==0) return m_array[pos]/TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat; - if(pos==size()) return 1-(m_array[size()-1]/TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat); - return (m_array[pos]-m_array[pos-1])/TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat; - }; - - ///set number of bins. - ///The actualy alocated size is one smaller than count, as the last bin is fixed with the range [get_fraction(size()-1,1] - void set_nbins(size_t nbins) {m_array.resize(nbins >= 1 ? nbins-1 : 0);}; - - ///return number of bins. - ///This is one larger than size, as the last bin is fixed with the range [get_fraction(size()-1,1] - inline size_t get_nbins() const {return size()+1;}; - - ///Get the matching bin for a given random value in the range [0,1). - ///A residual random number to calculate a position inside this bin is returned in residual_rnd - size_t get_bin(const Trandom& drnd,Trandom& residual_rnd) const { - if(size()==0) { - residual_rnd=drnd; - return 0; - } - T rnd=TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat*drnd; - auto it = std::upper_bound(m_array.begin(),m_array.end(),rnd); - - T basecont=0; - if(it!=m_array.begin()) basecont=*(it-1); - - T fullcont=TFCS1DFunction_Numeric<T,Trandom>::MaxValue; - if(it!=m_array.end()) fullcont=*it; - - T dcont=fullcont-basecont; - if(dcont>0) { - residual_rnd=(TFCS1DFunction_Numeric<T,Trandom>::MaxValueFloat*drnd-basecont) / dcont; - } else { - residual_rnd=0.5; - } - - if(it==m_array.end()) return size(); - return std::distance(m_array.begin(),it); - }; - - private: - TFCS1DFunction_Array<T> m_array; - inline size_t size() const {return m_array.size();}; - - //Use ClassDef without virtual functions. Saves 8 bytes per instance - ClassDefNV(TFCS1DFunction_HistogramContent,1) //TFCS1DFunction_HistogramContent -}; - -//Class to represent histogram bin edges. Trandom should be a type with a floating point range [0,1] -template<typename T,typename Trandom=float> class TFCS1DFunction_HistogramBinEdges -{ - public: - typedef TFCS1DFunction_size_t size_t; - typedef T value_type; - typedef Trandom random_type; - - TFCS1DFunction_HistogramBinEdges(size_t nbins=0):m_array(nbins+1) {}; - ~TFCS1DFunction_HistogramBinEdges() {}; - - std::size_t MemorySizeArray() const {return m_array.MemorySizeArray();}; - std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; - - ///set number of bins - void set_nbins(size_t nbins) {m_array.resize(nbins+1);}; - - ///return number of bins - inline size_t get_nbins() const {return size()-1;}; - - ///set position of lower edge of bins - void SetBinLowEdge(size_t pos,const T& value) {m_array[pos]=value;}; - - ///get position of lower edge of bins - inline const T& GetBinLowEdge(size_t pos) const {return m_array[pos];}; - - ///get the length of a bin - inline const T GetBinLength(size_t pos) const {return GetBinLowEdge(pos+1)-GetBinLowEdge(pos);}; - - ///set and get minimum - void SetMin(const T& value) {m_array[0]=value;}; - inline const T& GetMin() const {return m_array[0];}; - - ///set and get maximum - void SetMax(const T& value) {m_array[get_nbins()]=value;}; - inline const T& GetMax() const {return m_array[get_nbins()];}; - - ///set minimum and maximum - void SetMinMax(const T& valuemin,const T& valuemax) {SetMin(valuemin);SetMax(valuemax);}; - - ///Get length of interval of all bins - inline const T Length() const {return GetMax()-GetMin();}; - - ///return linear interpolated position for bin pos. Interpolation is done with a random value in the range [0,1] - inline T position(size_t pos,const Trandom& drnd) const { - return (1-drnd)*m_array[pos] + drnd*m_array[pos+1]; - }; - - ///return interpolated position for bin pos, such that histograming the position gives a linear slope m, - ///where m is in units of the bin width for bin pos. Interpolation is done with a random value in the range [0,1] - inline T position(size_t pos,Trandom m,const Trandom& drnd) const { - if(m>2) m=2; - if(m<-2) m=-2; - Trandom x=fabs(m)>0.001 ? (0.5*std::sqrt(m*(m+8*drnd-4)+4)-1)/m+0.5 : drnd; - return (1-x)*m_array[pos] + x*m_array[pos+1]; - }; - - private: - TFCS1DFunction_Array<T> m_array; - inline size_t size() const {return m_array.size();}; - - //Use ClassDef without virtual functions. Saves 8 bytes per instance - ClassDefNV(TFCS1DFunction_HistogramBinEdges,1) //TFCS1DFunction_HistogramBinEdges -}; - -class TFCS1DFunction_HistogramFloatBinEdges: public TFCS1DFunction_HistogramBinEdges<float,float> -{ - public: - TFCS1DFunction_HistogramFloatBinEdges(size_t nbins=0):TFCS1DFunction_HistogramBinEdges<float,float>(nbins) {}; - - ClassDefNV(TFCS1DFunction_HistogramFloatBinEdges,1) //TFCS1DFunction_HistogramFloatBinEdges -}; - -class TFCS1DFunction_HistogramDoubleBinEdges: public TFCS1DFunction_HistogramBinEdges<double,double> -{ - public: - TFCS1DFunction_HistogramDoubleBinEdges(size_t nbins=0):TFCS1DFunction_HistogramBinEdges<double,double>(nbins) {}; - - ClassDefNV(TFCS1DFunction_HistogramDoubleBinEdges,1) //TFCS1DFunction_HistogramDoubleBinEdges -}; - - - -//Class to represent histogram bin edges, where the interval between GetMin() and GetMax() -//can be stored as a different (smaller) data type Tint -//Trandom should be a type with a floating point range [0,1] -template<typename T,typename Tint,typename Trandom=float> class TFCS1DFunction_HistogramCompactBinEdges -{ - public: - typedef TFCS1DFunction_size_t size_t; - typedef T value_type; - typedef Trandom random_type; - typedef Tint internal_storage_type; - - TFCS1DFunction_HistogramCompactBinEdges(size_t nbins=0):m_array(nbins >= 1 ? nbins-1 : 0) {}; - ~TFCS1DFunction_HistogramCompactBinEdges() {}; - - std::size_t MemorySizeArray() const {return m_array.MemorySizeArray();}; - std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; - - ///set number of bins - void set_nbins(size_t nbins) {m_array.resize(nbins >= 1 ? nbins-1 : 0);}; - - ///return number of bins - inline size_t get_nbins() const {return size()+1;}; - - ///set position of lower edge of bins. Requires GetMin() and GetMax() to be set and may not be changed! - void SetBinLowEdge(size_t pos,const T& value) { - if(pos==0) { - SetMin(value); - return; - } - if(pos>=get_nbins()) { - SetMax(value); - return; - } - m_array[pos-1]=TFCS1DFunction_Numeric<Tint,T>::ExpandToMaxRange((value-GetMin())/Length()); - }; - - ///get position of lower edge of bins. Requires GetMin() and GetMax() to be set and may not be changed! - inline const T GetBinLowEdge(size_t pos) const { - if(pos==0) return GetMin(); - if(pos>=get_nbins()) return GetMax(); - return GetMin()+Length()*TFCS1DFunction_Numeric<Tint,T>::ToNormalizedRange(m_array[pos-1]); - }; - - ///get the length of a bin - inline const T GetBinLength(size_t pos) const {return GetBinLowEdge(pos+1)-GetBinLowEdge(pos);}; - - ///set and get minimum - void SetMin(const T& value) {m_Min=value;}; - inline const T& GetMin() const {return m_Min;}; - - ///set and get maximum - void SetMax(const T& value) {m_Max=value;}; - inline const T& GetMax() const {return m_Max;}; - - ///set minimum and maximum - void SetMinMax(const T& valuemin,const T& valuemax) {SetMin(valuemin);SetMax(valuemax);}; - - ///Get length of interval of all bins - inline const T Length() const {return GetMax()-GetMin();}; - - ///return linear interpolated position for bin pos. Interpolation is done with a random value in the range [0,1] - inline T position(size_t pos,const Trandom& drnd) const { - T pos1=GetBinLowEdge(pos); - T pos2=GetBinLowEdge(pos+1); - return (1-drnd)*pos1 + drnd*pos2; - }; - - ///return interpolated position for bin pos, such that histograming the position gives a linear slope m, - ///where m is in units of the bin width for bin pos. Interpolation is done with a random value in the range [0,1] - inline T position(size_t pos,Trandom m,const Trandom& drnd) const { - if(m>2) m=2; - if(m<-2) m=-2; - Trandom x=(0.5*std::sqrt(m*(m+8*drnd-4)+4)-1)/m+0.5; - T pos1=GetBinLowEdge(pos); - T pos2=GetBinLowEdge(pos+1); - return (1-x)*pos1 + x*pos2; - }; - - private: - TFCS1DFunction_Array<Tint> m_array; - inline size_t size() const {return m_array.size();}; - T m_Min{0}; - T m_Max{0}; - - ClassDefNV(TFCS1DFunction_HistogramCompactBinEdges,1) //TFCS1DFunction_HistogramCompactBinEdges -}; - -class TFCS1DFunction_HistogramInt8BinEdges: public TFCS1DFunction_HistogramCompactBinEdges<float,uint8_t,float> -{ - public: - TFCS1DFunction_HistogramInt8BinEdges(size_t nbins=0):TFCS1DFunction_HistogramCompactBinEdges<float,uint8_t,float>(nbins) {}; - - ClassDefNV(TFCS1DFunction_HistogramInt8BinEdges,1) //TFCS1DFunction_HistogramInt8BinEdges -}; - -class TFCS1DFunction_HistogramInt16BinEdges: public TFCS1DFunction_HistogramCompactBinEdges<float,uint16_t,float> -{ - public: - TFCS1DFunction_HistogramInt16BinEdges(size_t nbins=0):TFCS1DFunction_HistogramCompactBinEdges<float,uint16_t,float>(nbins) {}; - - ClassDefNV(TFCS1DFunction_HistogramInt16BinEdges,1) //TFCS1DFunction_HistogramInt16BinEdges -}; - -class TFCS1DFunction_HistogramInt32BinEdges: public TFCS1DFunction_HistogramCompactBinEdges<float,uint32_t,float> -{ - public: - TFCS1DFunction_HistogramInt32BinEdges(size_t nbins=0):TFCS1DFunction_HistogramCompactBinEdges<float,uint32_t,float>(nbins) {}; - - ClassDefNV(TFCS1DFunction_HistogramInt32BinEdges,1) //TFCS1DFunction_HistogramInt32BinEdges -}; - template <typename Txvec, typename Ty,typename Trandom=float> class TFCS1DFunctionTemplateHistogram:public TFCS1DFunction { public: @@ -486,78 +98,6 @@ template <typename Txvec, typename Ty,typename Trandom=float> class TFCS1DFuncti ClassDef(TFCS1DFunctionTemplateHistogram,1) //TFCS1DFunctionTemplateHistogram }; -template <typename Txvec, typename Ty,typename Trandom=float> class TFCS1DFunctionTemplateInterpolationHistogram:public TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom> -{ - public: - TFCS1DFunctionTemplateInterpolationHistogram(TH1* hist=nullptr):TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom>(hist) {}; - - using TFCS1DFunction::rnd_to_fct; - using TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom>::get_nbins; - using TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom>::m_HistoContents; - using TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom>::m_HistoBorders; - - ///Function gets random number rnd in the range [0,1) as argument - ///and returns function value according to a histogram distribution. - ///A linear interpolation is done within each bin - virtual double rnd_to_fct(double rnd) const { - size_t nbins=get_nbins(); - if(nbins==0) return 0; - Trandom residual_rnd; - size_t ibin=m_HistoContents.get_bin(rnd,residual_rnd); - - Trandom frac=m_HistoContents.get_fraction(ibin); - - Trandom dfrac; - auto l=m_HistoBorders.GetBinLength(ibin); - Trandom dfracprev; - auto lprev=l; - if(ibin>0) { - Trandom fracprev=m_HistoContents.get_fraction(ibin-1); - dfrac=frac-fracprev; - if(ibin>1) dfracprev=fracprev-m_HistoContents.get_fraction(ibin-2); - else dfracprev=fracprev; - lprev=m_HistoBorders.GetBinLength(ibin-1); - } else { - dfrac=frac; - dfracprev=dfrac; - } - - Trandom dfracnext; - auto lnext=l; - if(ibin<nbins-1) { - dfracnext=m_HistoContents.get_fraction(ibin+1)-frac; - lnext=m_HistoBorders.GetBinLength(ibin+1); - } else { - dfracnext=dfrac; - } - - Trandom m; - if(dfrac>0) { - /* - //approximately readable version of the code below - //density in bin is dfracX/lX - Trandom mnext=dfracnext/lnext-dfrac/l; //change in density to next bin - mnext/=0.5*(l+lnext); //normalize change in density to distance between bins - Trandom mprev=dfrac/l-dfracprev/lprev; //change in density to previous bin - mprev/=0.5*(l+lprev); //normalize change in density to distance between bins - m=0.5*(mnext+mprev); //average the two - m*=l; //m is needed inside this bin, so multiply by size of this bin (matches normalization to distance between bins above) - m/=dfrac/l; //finally, m is the slope in this bin, given that this bin was already selected. So overall normalize to density inside this bin - */ - Trandom mnext=dfracnext/lnext-dfrac/l; - mnext/=l+lnext; - Trandom mprev=dfrac/l-dfracprev/lprev; - mprev/=l+lprev; - m=(mnext+mprev)*l*l/dfrac; - } else m=0; - - //std::cout<<"fbin="<<ibin<<" fx="<<m_HistoBorders.GetBinLowEdge(ibin)<<" frac="<<m_HistoContents.get_fraction(ibin)<<" dfracprev="<<dfracprev<<" dfrac="<<dfrac<<" dfracnext="<<dfracnext<<" dfracprev-dfrac="<<dfracprev-dfrac<<" dfracnext-dfrac="<<dfracnext-dfrac<<" m="<<m<<" residual_rnd="<<residual_rnd<<std::endl; - return m_HistoBorders.position(ibin,m,residual_rnd); - } - - ClassDef(TFCS1DFunctionTemplateInterpolationHistogram,1) //TFCS1DFunctionTemplateInterpolationHistogram -}; - class TFCS1DFunctionInt8Int8Histogram: public TFCS1DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float> { public: @@ -598,76 +138,8 @@ class TFCS1DFunctionInt16Int32Histogram: public TFCS1DFunctionTemplateHistogram< ClassDef(TFCS1DFunctionInt16Int32Histogram,1) //TFCS1DFunctionInt16Int32Histogram }; -class TFCS1DFunctionInt8Int8InterpolationHistogram: public TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float> -{ - public: - TFCS1DFunctionInt8Int8InterpolationHistogram(TH1* h=nullptr):TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float>(h) {}; - - ClassDef(TFCS1DFunctionInt8Int8InterpolationHistogram,1) //TFCS1DFunctionInt8Int8InterpolationHistogram -}; - -class TFCS1DFunctionInt8Int16InterpolationHistogram: public TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float> -{ - public: - TFCS1DFunctionInt8Int16InterpolationHistogram(TH1* h=nullptr):TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float>(h) {}; - - ClassDef(TFCS1DFunctionInt8Int16InterpolationHistogram,1) //TFCS1DFunctionInt8Int16InterpolationHistogram -}; - -class TFCS1DFunctionInt16Int16InterpolationHistogram: public TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float> -{ - public: - TFCS1DFunctionInt16Int16InterpolationHistogram(TH1* h=nullptr):TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float>(h) {}; - - ClassDef(TFCS1DFunctionInt16Int16InterpolationHistogram,1) //TFCS1DFunctionInt16Int16InterpolationHistogram -}; - -class TFCS1DFunctionInt16Int32InterpolationHistogram: public TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float> -{ - public: - TFCS1DFunctionInt16Int32InterpolationHistogram(TH1* h=nullptr):TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float>(h) {}; - - ClassDef(TFCS1DFunctionInt16Int32InterpolationHistogram,1) //TFCS1DFunctionInt16Int32InterpolationHistogram -}; - - - #if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) -#pragma link C++ class TFCS1DFunction_Numeric<uint8_t,float>+; -#pragma link C++ class TFCS1DFunction_Numeric<uint16_t,float>+; -#pragma link C++ class TFCS1DFunction_Numeric<uint32_t,float>+; -#pragma link C++ class TFCS1DFunction_Numeric<float,float>+; -#pragma link C++ class TFCS1DFunction_Numeric<double,float>+; -#pragma link C++ class TFCS1DFunction_Numeric<double,double>+; - -#pragma link C++ class TFCS1DFunction_Array<float>-; -#pragma link C++ class TFCS1DFunction_Array<double>-; -#pragma link C++ class TFCS1DFunction_Array<uint8_t>-; -#pragma link C++ class TFCS1DFunction_Array<uint16_t>-; -#pragma link C++ class TFCS1DFunction_Array<uint32_t>-; - -#pragma link C++ class TFCS1DFunction_HistogramContent<float,float>+; -#pragma link C++ class TFCS1DFunction_HistogramContent<double,float>+; -#pragma link C++ class TFCS1DFunction_HistogramContent<double,double>+; -#pragma link C++ class TFCS1DFunction_HistogramContent<uint8_t,float>+; -#pragma link C++ class TFCS1DFunction_HistogramContent<uint16_t,float>+; -#pragma link C++ class TFCS1DFunction_HistogramContent<uint32_t,float>+; - -#pragma link C++ class TFCS1DFunction_HistogramBinEdges<float,float>+; -#pragma link C++ class TFCS1DFunction_HistogramBinEdges<double,float>+; -#pragma link C++ class TFCS1DFunction_HistogramBinEdges<double,double>+; - -#pragma link C++ class TFCS1DFunction_HistogramCompactBinEdges<float,uint8_t,float>+; -#pragma link C++ class TFCS1DFunction_HistogramCompactBinEdges<float,uint16_t,float>+; -#pragma link C++ class TFCS1DFunction_HistogramCompactBinEdges<float,uint32_t,float>+; - -#pragma link C++ class TFCS1DFunction_HistogramInt8BinEdges+; -#pragma link C++ class TFCS1DFunction_HistogramInt16BinEdges+; -#pragma link C++ class TFCS1DFunction_HistogramInt32BinEdges+; -#pragma link C++ class TFCS1DFunction_HistogramFloatBinEdges+; -#pragma link C++ class TFCS1DFunction_HistogramDoubleBinEdges+; - #pragma link C++ class TFCS1DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float>+; #pragma link C++ class TFCS1DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float>+; #pragma link C++ class TFCS1DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint32_t,float>+; @@ -680,16 +152,6 @@ class TFCS1DFunctionInt16Int32InterpolationHistogram: public TFCS1DFunctionTempl #pragma link C++ class TFCS1DFunctionInt16Int16Histogram+; #pragma link C++ class TFCS1DFunctionInt16Int32Histogram+; -#pragma link C++ class TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float>+; -#pragma link C++ class TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float>+; -#pragma link C++ class TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float>+; -#pragma link C++ class TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float>+; - -#pragma link C++ class TFCS1DFunctionInt8Int8InterpolationHistogram+; -#pragma link C++ class TFCS1DFunctionInt8Int16InterpolationHistogram+; -#pragma link C++ class TFCS1DFunctionInt16Int16InterpolationHistogram+; -#pragma link C++ class TFCS1DFunctionInt16Int32InterpolationHistogram+; - #endif #endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateInterpolationHistogram.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateInterpolationHistogram.h new file mode 100644 index 0000000000000000000000000000000000000000..a9ec021859f7c9373098ea5fae3bebae530bca46 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS1DFunctionTemplateInterpolationHistogram.h @@ -0,0 +1,128 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ISF_FASTCALOSIMEVENT_TFCS1DFunctionTemplateInterpolationHistogram_h +#define ISF_FASTCALOSIMEVENT_TFCS1DFunctionTemplateInterpolationHistogram_h + +#include "ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHistogram.h" + +template <typename Txvec, typename Ty,typename Trandom=float> class TFCS1DFunctionTemplateInterpolationHistogram:public TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom> +{ + public: + TFCS1DFunctionTemplateInterpolationHistogram(TH1* hist=nullptr):TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom>(hist) {}; + + using TFCS1DFunction::rnd_to_fct; + using TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom>::get_nbins; + using TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom>::m_HistoContents; + using TFCS1DFunctionTemplateHistogram<Txvec,Ty,Trandom>::m_HistoBorders; + + ///Function gets random number rnd in the range [0,1) as argument + ///and returns function value according to a histogram distribution. + ///A linear interpolation is done within each bin + virtual double rnd_to_fct(double rnd) const { + size_t nbins=get_nbins(); + if(nbins==0) return 0; + Trandom residual_rnd; + size_t ibin=m_HistoContents.get_bin(rnd,residual_rnd); + + Trandom frac=m_HistoContents.get_fraction(ibin); + + Trandom dfrac; + auto l=m_HistoBorders.GetBinLength(ibin); + Trandom dfracprev; + auto lprev=l; + if(ibin>0) { + Trandom fracprev=m_HistoContents.get_fraction(ibin-1); + dfrac=frac-fracprev; + if(ibin>1) dfracprev=fracprev-m_HistoContents.get_fraction(ibin-2); + else dfracprev=fracprev; + lprev=m_HistoBorders.GetBinLength(ibin-1); + } else { + dfrac=frac; + dfracprev=dfrac; + } + + Trandom dfracnext; + auto lnext=l; + if(ibin<nbins-1) { + dfracnext=m_HistoContents.get_fraction(ibin+1)-frac; + lnext=m_HistoBorders.GetBinLength(ibin+1); + } else { + dfracnext=dfrac; + } + + Trandom m; + if(dfrac>0) { + /* + //approximately readable version of the code below + //density in bin is dfracX/lX + Trandom mnext=dfracnext/lnext-dfrac/l; //change in density to next bin + mnext/=0.5*(l+lnext); //normalize change in density to distance between bins + Trandom mprev=dfrac/l-dfracprev/lprev; //change in density to previous bin + mprev/=0.5*(l+lprev); //normalize change in density to distance between bins + m=0.5*(mnext+mprev); //average the two + m*=l; //m is needed inside this bin, so multiply by size of this bin (matches normalization to distance between bins above) + m/=dfrac/l; //finally, m is the slope in this bin, given that this bin was already selected. So overall normalize to density inside this bin + */ + Trandom mnext=dfracnext/lnext-dfrac/l; + mnext/=l+lnext; + Trandom mprev=dfrac/l-dfracprev/lprev; + mprev/=l+lprev; + m=(mnext+mprev)*l*l/dfrac; + } else m=0; + + //std::cout<<"fbin="<<ibin<<" fx="<<m_HistoBorders.GetBinLowEdge(ibin)<<" frac="<<m_HistoContents.get_fraction(ibin)<<" dfracprev="<<dfracprev<<" dfrac="<<dfrac<<" dfracnext="<<dfracnext<<" dfracprev-dfrac="<<dfracprev-dfrac<<" dfracnext-dfrac="<<dfracnext-dfrac<<" m="<<m<<" residual_rnd="<<residual_rnd<<std::endl; + return m_HistoBorders.position(ibin,m,residual_rnd); + } + + ClassDef(TFCS1DFunctionTemplateInterpolationHistogram,1) //TFCS1DFunctionTemplateInterpolationHistogram +}; + +class TFCS1DFunctionInt8Int8InterpolationHistogram: public TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float> +{ + public: + TFCS1DFunctionInt8Int8InterpolationHistogram(TH1* h=nullptr):TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float>(h) {}; + + ClassDef(TFCS1DFunctionInt8Int8InterpolationHistogram,1) //TFCS1DFunctionInt8Int8InterpolationHistogram +}; + +class TFCS1DFunctionInt8Int16InterpolationHistogram: public TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float> +{ + public: + TFCS1DFunctionInt8Int16InterpolationHistogram(TH1* h=nullptr):TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float>(h) {}; + + ClassDef(TFCS1DFunctionInt8Int16InterpolationHistogram,1) //TFCS1DFunctionInt8Int16InterpolationHistogram +}; + +class TFCS1DFunctionInt16Int16InterpolationHistogram: public TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float> +{ + public: + TFCS1DFunctionInt16Int16InterpolationHistogram(TH1* h=nullptr):TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float>(h) {}; + + ClassDef(TFCS1DFunctionInt16Int16InterpolationHistogram,1) //TFCS1DFunctionInt16Int16InterpolationHistogram +}; + +class TFCS1DFunctionInt16Int32InterpolationHistogram: public TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float> +{ + public: + TFCS1DFunctionInt16Int32InterpolationHistogram(TH1* h=nullptr):TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float>(h) {}; + + ClassDef(TFCS1DFunctionInt16Int32InterpolationHistogram,1) //TFCS1DFunctionInt16Int32InterpolationHistogram +}; + + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float>+; +#pragma link C++ class TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float>+; +#pragma link C++ class TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float>+; +#pragma link C++ class TFCS1DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float>+; + +#pragma link C++ class TFCS1DFunctionInt8Int8InterpolationHistogram+; +#pragma link C++ class TFCS1DFunctionInt8Int16InterpolationHistogram+; +#pragma link C++ class TFCS1DFunctionInt16Int16InterpolationHistogram+; +#pragma link C++ class TFCS1DFunctionInt16Int32InterpolationHistogram+; + +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunction.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunction.h index d42cd394eaca50ab24da28858bcc42f75e684215..23001019539c6ae39ee8ecb601238bcc81bf9dbc 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunction.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunction.h @@ -6,6 +6,7 @@ #define ISF_FASTCALOSIMEVENT_TFCS2DFunction_h #include "ISF_FastCaloSimEvent/TFCSFunction.h" +#include <vector> class TH2; @@ -20,6 +21,10 @@ class TFCS2DFunction:public TFCSFunction virtual void rnd_to_fct(float& valuex,float& valuey,float rnd0,float rnd1) const = 0; virtual void rnd_to_fct(float value[],const float rnd[]) const; + static double CheckAndIntegrate2DHistogram(const TH2* hist, std::vector<double>& integral_vec,int& first,int& last); + + static void unit_test(TH2* hist=nullptr,TFCS2DFunction* rtof=nullptr,const char* outfilename="TFCS2DFunction_unit_test.root",int nrnd=10000000); + static void unit_tests(TH2* hist=nullptr,const char* outfilename="TFCS2DFunction_unit_test.root",int nrnd=10000000); private: ClassDef(TFCS2DFunction,1) //TFCS2DFunction diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionLateralShapeParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionLateralShapeParametrization.h new file mode 100644 index 0000000000000000000000000000000000000000..0cd3392f9cf0999c3046a940f68ddbe86ee3e94b --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionLateralShapeParametrization.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TFCS2DFunctionLateralShapeParametrization_h +#define TFCS2DFunctionLateralShapeParametrization_h + +#include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h" +#include "ISF_FastCaloSimEvent/TFCS2DFunction.h" +#include "ISF_FastCaloSimEvent/TFCSTruthState.h" + +class TH2; + +class TFCS2DFunctionLateralShapeParametrization:public TFCSLateralShapeParametrizationHitBase { +public: + TFCS2DFunctionLateralShapeParametrization(const char* name=nullptr, const char* title=nullptr); + ~TFCS2DFunctionLateralShapeParametrization(); + + ///Status bit for FCS needs + enum FCSStatusBits { + k_phi_symmetric = BIT(15) ///< Set this bit to simulate phi symmetric histograms + }; + + bool is_phi_symmetric() const {return TestBit(k_phi_symmetric);}; + virtual void set_phi_symmetric() {SetBit(k_phi_symmetric);}; + virtual void reset_phi_symmetric() {ResetBit(k_phi_symmetric);}; + + /// set the desired number of hits + void set_number_of_hits(float nhits); + + float get_number_of_expected_hits() const {return m_nhits;}; + + ///default for this class is to simulate get_number_of_expected_hits() hits, + ///which gives fluctuations sigma^2=1/get_number_of_expected_hits() + virtual double get_sigma2_fluctuation(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const override; + + /// default for this class is to simulate get_number_of_expected_hits() hits + virtual int get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const override; + + /// simulated one hit position with weight that should be put into simulstate + /// sometime later all hit weights should be resacled such that their final sum is simulstate->E(sample) + /// someone also needs to map all hits into cells + virtual FCSReturnCode simulate_hit(Hit& hit,TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) override; + + /// Init from function + bool Initialize(TFCS2DFunction* func,float nhits=-1); + + TFCS2DFunction* function() {return m_function;}; + const TFCS2DFunction* function() const {return m_function;}; + + virtual void Print(Option_t *option = "") const override; +protected: + /// Histogram to be used for the shape simulation + TFCS2DFunction* m_function; + float m_nhits; + +private: + + ClassDefOverride(TFCS2DFunctionLateralShapeParametrization,2) //TFCS2DFunctionLateralShapeParametrization +}; + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCS2DFunctionLateralShapeParametrization+; +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionTemplateHistogram.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionTemplateHistogram.h new file mode 100644 index 0000000000000000000000000000000000000000..2420053690bc7f135ae0cb6b7a8766aede3353b2 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionTemplateHistogram.h @@ -0,0 +1,287 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ISF_FASTCALOSIMEVENT_TFCS2DFunctionTemplateHistogram_h +#define ISF_FASTCALOSIMEVENT_TFCS2DFunctionTemplateHistogram_h + +#include "TFCS2DFunction.h" +#include "ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHelpers.h" +#include "TH1.h" +#include "TH2.h" +#include "TBuffer.h" + +#include <iostream> + +template <typename Txvec, typename Tyvec, typename Tz, typename Trandom=float> class TFCS2DFunctionTemplateHistogram:public TFCS2DFunction +{ + public: + typedef TFCS1DFunction_size_t size_t; + typedef Trandom random_type; + typedef Txvec xvec_type; + typedef Tyvec yvec_type; + typedef Tz z_value_type; + + TFCS2DFunctionTemplateHistogram(TH2* hist=nullptr) {if(hist) Initialize(hist);}; + ~TFCS2DFunctionTemplateHistogram() {}; + + std::size_t MemorySizeArray() const {return m_HistoBordersx.MemorySizeArray()+m_HistoBordersy.MemorySizeArray()+m_HistoContents.MemorySizeArray();}; + std::size_t MemorySize() const {return sizeof(*this)+MemorySizeArray();}; + + ///set number of bins + void set_nbins(size_t nbinsx, size_t nbinsy) {m_HistoBordersx.set_nbins(nbinsx); m_HistoBordersy.set_nbins(nbinsy); m_HistoContents.set_nbins(nbinsx*nbinsy);}; + + ///return number of bins + inline size_t get_nbins() const {return m_HistoContents.get_nbins();}; + // inline size_t get_nbinsx() const {return m_HistoBordersx.get_nbins();}; + // inline size_t get_nbinsy() const {return m_HistoBordersy.get_nbins();}; + + + ///Initialize from root histogram. Depending on the precision of the x- and y-axis, bins are merged if numerical identical + virtual void Initialize(const TH2* hist) { + Int_t nbinsx = hist->GetNbinsX(); + Int_t nbinsy = hist->GetNbinsY(); + std::vector<double> temp_HistoContents; + int first,last; + double integral=CheckAndIntegrate2DHistogram(hist, temp_HistoContents,first,last); + printf("initializing 2D template..."); + if(integral<=0) { + set_nbins(0, 0); + } else { + set_nbins( nbinsx, nbinsy ); + + //m_HistoBordersx.SetMinMax(hist->GetXaxis()->GetBinLowEdge(first+1),hist->GetXaxis()->GetBinUpEdge(last+1)); + m_HistoBordersx.SetMinMax(hist->GetXaxis()->GetBinLowEdge(1),hist->GetXaxis()->GetBinUpEdge(nbinsx) ); + m_HistoBordersy.SetMinMax(hist->GetYaxis()->GetBinLowEdge(1),hist->GetYaxis()->GetBinUpEdge(nbinsy) ); + //Int_t ihist=0; + for( Int_t ibinx=1; ibinx<=hist->GetNbinsX(); ++ibinx ) { + m_HistoBordersx.SetBinLowEdge(ibinx,hist->GetXaxis()->GetBinLowEdge(ibinx+1)); +// if(ihist>0) if(m_HistoBorders.GetBinLowEdge(ihist-1)==m_HistoBorders.GetBinLowEdge(ihist)) { +// std::cout<<"Skip bin="<<ibin+1<<" x="<<hist->GetXaxis()->GetBinLowEdge(ibin+1)<<" fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<std::endl; +// --ihist; +// std::cout<<" bin="<<ibin <<" x="<<hist->GetXaxis()->GetBinLowEdge(ibin )<<" fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<std::endl; +// } + } //for + for( Int_t ibiny=1;ibiny<=hist->GetNbinsY();++ibiny ) { + m_HistoBordersy.SetBinLowEdge(ibiny,hist->GetYaxis()->GetBinLowEdge(ibiny+1)); +// if(ihist>0) if(m_HistoBorders.GetBinLowEdge(ihist-1)==m_HistoBorders.GetBinLowEdge(ihist)) { +// std::cout<<"Skip bin="<<ibin+1<<" x="<<hist->GetXaxis()->GetBinLowEdge(ibin+1)<<" fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<std::endl; +// --ihist; +// std::cout<<" bin="<<ibin <<" x="<<hist->GetXaxis()->GetBinLowEdge(ibin )<<" fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<std::endl; +// } + } //for + + for( Int_t ibinx=1; ibinx<=hist->GetNbinsX(); ++ibinx ) + for( Int_t ibiny=1; ibiny<=hist->GetNbinsY(); ++ibiny ) + { + int globalbin = (ibinx-1)*hist->GetNbinsY() + ibiny - 1; + m_HistoContents.set_fraction(globalbin, temp_HistoContents[globalbin]/integral); +// if(ihist>0) if(m_HistoContents.get_fraction(ihist-1)==m_HistoContents.get_fraction(ihist)) { +// std::cout<<"Skip fbin="<<ihist<<" fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<" frac="<<m_HistoContents.get_fraction(ihist)<<std::endl; +// --ihist; +// std::cout<<" fbin="<<ihist<<" fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<" frac="<<m_HistoContents.get_fraction(ihist)<<std::endl; +// } + +// std::cout<<"bin="<<ibin+1<<" fbin="<<ihist<<"/"<<m_HistoBorders.get_nbins()<<" x=["<<hist->GetXaxis()->GetBinLowEdge(ibin+1)<<","<<hist->GetXaxis()->GetBinUpEdge(ibin+1)<<"] fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<" int="<<temp_HistoContents[ibin]/integral<<" frac="<<m_HistoContents.get_fraction(ihist)<<std::endl; + +// ++ihist; + } +// if(ihist!=nbins) { +// set_nbins(ihist); +// m_HistoBorders.SetMinMax(hist->GetXaxis()->GetBinLowEdge(first+1),hist->GetXaxis()->GetBinUpEdge(last+1)); +// } + }//for ibinx + }//for ibiny + +/* + for( Int_t ibiny=1; ibiny<=hist->GetNbinsY(); ++ibiny ) + for( Int_t ibinx=1; ibinx<=hist->GetNbinsX(); ++ibinx ) + { + int globalbin = (ibiny-1)*hist->GetNbinsX() + ibinx - 1; + m_HistoContents.set_fraction(globalbin, temp_HistoContents[globalbin]/integral); +// if(ihist>0) if(m_HistoContents.get_fraction(ihist-1)==m_HistoContents.get_fraction(ihist)) { +// std::cout<<"Skip fbin="<<ihist<<" fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<" frac="<<m_HistoContents.get_fraction(ihist)<<std::endl; +// --ihist; +// std::cout<<" fbin="<<ihist<<" fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<" frac="<<m_HistoContents.get_fraction(ihist)<<std::endl; +// } + +// std::cout<<"bin="<<ibin+1<<" fbin="<<ihist<<"/"<<m_HistoBorders.get_nbins()<<" x=["<<hist->GetXaxis()->GetBinLowEdge(ibin+1)<<","<<hist->GetXaxis()->GetBinUpEdge(ibin+1)<<"] fx="<<m_HistoBorders.GetBinLowEdge(ihist)<<" int="<<temp_HistoContents[ibin]/integral<<" frac="<<m_HistoContents.get_fraction(ihist)<<std::endl; + +// ++ihist; + } +// if(ihist!=nbins) { +// set_nbins(ihist); +// m_HistoBorders.SetMinMax(hist->GetXaxis()->GetBinLowEdge(first+1),hist->GetXaxis()->GetBinUpEdge(last+1)); +// } + }//for ibinx + }//for ibiny +*/ + // using TFCS2DFunction::rnd_to_fct; + + ///Function gets random number rnd in the range [0,1) as argument + ///and returns function value according to a histogram distribution + + using TFCS2DFunction::rnd_to_fct; + + virtual void rnd_to_fct(float& valuex,float& valuey,float rnd) const { + if(m_HistoContents.get_nbins()==0) { valuex = 0.0; valuey = 0.0; } + Trandom residual_rnd; + size_t ibin=m_HistoContents.get_bin(rnd,residual_rnd); + int ibiny = ibin % m_HistoBordersy.get_nbins() ; + int ibinx = ibin / m_HistoBordersy.get_nbins() ; + valuex = m_HistoBordersx.position(ibinx, 0.5); + valuey = m_HistoBordersy.position(ibiny,residual_rnd); + //valuex = 2.0+ 0.3*rnd; + //valuey = 1200.0 + rnd*500.0; + } + + virtual void rnd_to_fct(float& valuex,float& valuey,float rnd, float rnd2) const { + if(m_HistoContents.get_nbins()==0) { valuex = 0.0; valuey = 0.0; } + Trandom residual_rnd; + size_t ibin=m_HistoContents.get_bin(rnd,residual_rnd); + int ibiny = ibin % m_HistoBordersy.get_nbins(); //printf("%d ", m_HistoBordersy.get_nbins() ); + int ibinx = ibin / m_HistoBordersy.get_nbins(); //printf("%d ", m_HistoBordersx.get_nbins() ); getchar(); + valuex = m_HistoBordersx.position(ibinx, rnd2); + valuey = m_HistoBordersy.position(ibiny,residual_rnd); + //valuex = 2.0+ rnd; + //valuey = 1200.0 + rnd2*500.0; + } + /* + virtual void rnd_to_fct(float& valuex,float& valuey,float rnd, float rnd2) const { + if(m_HistoContents.get_nbins()==0) { valuex = 0.0; valuey = 0.0; } + Trandom residual_rnd; + size_t ibin=m_HistoContents.get_bin(rnd,residual_rnd); + int ibiny = ibin / m_HistoBordersx.get_nbins(); //printf("%d ", m_HistoBordersy.get_nbins() ); + int ibinx = ibin % m_HistoBordersx.get_nbins(); //printf("%d ", m_HistoBordersx.get_nbins() ); getchar(); + valuex = m_HistoBordersx.position(ibinx, rnd2); + valuey = m_HistoBordersy.position(ibiny,residual_rnd); + //valuex = 2.0+ rnd; + //valuey = 1200.0 + rnd2*500.0; + }*/ + + inline const Txvec& get_HistoBordersx() const {return m_HistoBordersx;}; + inline const Tyvec& get_HistoBordersy() const {return m_HistoBordersy;}; + + /////inline void get_XYZfromGlobal(int &ix, int &iy, int &iz, int global) const {hist;}; + + inline Txvec& get_HistoBordersx() {return m_HistoBordersx;}; + inline Tyvec& get_HistoBordersy() {return m_HistoBordersy;}; + + inline const TFCS1DFunction_HistogramContent<Tz,Trandom>& get_HistoContents() const {return m_HistoContents;}; + inline TFCS1DFunction_HistogramContent<Tz,Trandom>& get_HistoContents() {return m_HistoContents;}; + + protected: + Txvec m_HistoBordersx; + Tyvec m_HistoBordersy; + TFCS1DFunction_HistogramContent<Tz,Trandom> m_HistoContents; + + private: + + ClassDef(TFCS2DFunctionTemplateHistogram,1) //TFCS2DFunctionTemplateHistogram +}; + + + +class TFCS2DFunctionInt8Int8Int8Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float> +{ + public: + TFCS2DFunctionInt8Int8Int8Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int8Int8Histogram,1) //TFCS2DFunctionInt8Int8Int8Histogram +}; + +class TFCS2DFunctionInt8Int8Int16Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float> +{ + public: + TFCS2DFunctionInt8Int8Int16Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int8Int16Histogram,1) //TFCS2DFunctionInt8Int8Int16Histogram +}; + +class TFCS2DFunctionInt8Int8Int32Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint32_t,float> +{ + public: + TFCS2DFunctionInt8Int8Int32Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint32_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int8Int32Histogram,1) //TFCS2DFunctionInt8Int8Int32Histogram +}; + + + +class TFCS2DFunctionInt8Int16Int8Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint8_t,float> +{ + public: + TFCS2DFunctionInt8Int16Int8Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint8_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int16Int8Histogram,1) //TFCS2DFunctionInt8Int16Int8Histogram +}; + +class TFCS2DFunctionInt8Int16Int16Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float> +{ + public: + TFCS2DFunctionInt8Int16Int16Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int16Int16Histogram,1) //TFCS2DFunctionInt8Int16Int16Histogram +}; + +class TFCS2DFunctionInt8Int16Int32Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float> +{ + public: + TFCS2DFunctionInt8Int16Int32Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int16Int32Histogram,1) //TFCS2DFunctionInt8Int16Int32Histogram +}; + + + +class TFCS2DFunctionInt16Int16Int8Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint8_t,float> +{ + public: + TFCS2DFunctionInt16Int16Int8Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint8_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt16Int16Int8Histogram,1) //TFCS2DFunctionInt16Int16Int8Histogram +}; + +class TFCS2DFunctionInt16Int16Int16Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float> +{ + public: + TFCS2DFunctionInt16Int16Int16Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt16Int16Int16Histogram,1) //TFCS2DFunctionInt16Int16Int16Histogram +}; + +class TFCS2DFunctionInt16Int16Int32Histogram: public TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float> +{ + public: + TFCS2DFunctionInt16Int16Int32Histogram(TH2* h=nullptr):TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt16Int16Int32Histogram,1) //TFCS2DFunctionInt16Int16Int32Histogram +}; + + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint32_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint32_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint32_t,float>+; + +#pragma link C++ class TFCS2DFunctionInt8Int8Int8Histogram+; +#pragma link C++ class TFCS2DFunctionInt8Int8Int16Histogram+; +#pragma link C++ class TFCS2DFunctionInt8Int8Int32Histogram+; + +#pragma link C++ class TFCS2DFunctionInt8Int16Int8Histogram+; +#pragma link C++ class TFCS2DFunctionInt8Int16Int16Histogram+; +#pragma link C++ class TFCS2DFunctionInt8Int16Int32Histogram+; + +#pragma link C++ class TFCS2DFunctionInt16Int16Int8Histogram+; +#pragma link C++ class TFCS2DFunctionInt16Int16Int16Histogram+; +#pragma link C++ class TFCS2DFunctionInt16Int16Int32Histogram+; + +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionTemplateInterpolationHistogram.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionTemplateInterpolationHistogram.h new file mode 100644 index 0000000000000000000000000000000000000000..ac376b24dcebcea16ecbaf72ac928278d8e2a169 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCS2DFunctionTemplateInterpolationHistogram.h @@ -0,0 +1,189 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ISF_FASTCALOSIMEVENT_TFCS2DFunctionTemplateInterpolationHistogram_h +#define ISF_FASTCALOSIMEVENT_TFCS2DFunctionTemplateInterpolationHistogram_h + +#include "TFCS2DFunction.h" +#include "ISF_FastCaloSimEvent/TFCS2DFunctionTemplateHistogram.h" +#include "TH1.h" +#include "TH2.h" +#include "TBuffer.h" + +#include <iostream> + +template <typename Txvec, typename Tyvec, typename Tz ,typename Trandom=float> class TFCS2DFunctionTemplateInterpolationHistogram:public TFCS2DFunctionTemplateHistogram<Txvec,Tyvec,Tz,Trandom> +{ + public: + TFCS2DFunctionTemplateInterpolationHistogram(TH2* hist=nullptr):TFCS2DFunctionTemplateHistogram<Txvec,Tyvec,Tz,Trandom>(hist) {}; + + using TFCS2DFunctionTemplateHistogram<Txvec,Tyvec,Tz,Trandom>::rnd_to_fct; + using TFCS2DFunctionTemplateHistogram<Txvec,Tyvec,Tz,Trandom>::get_nbins; + using TFCS2DFunctionTemplateHistogram<Txvec,Tyvec,Tz,Trandom>::m_HistoContents; + using TFCS2DFunctionTemplateHistogram<Txvec,Tyvec,Tz,Trandom>::m_HistoBordersx; + using TFCS2DFunctionTemplateHistogram<Txvec,Tyvec,Tz,Trandom>::m_HistoBordersy; + + ///Function gets random number rnd in the range [0,1) as argument + ///and returns function value according to a histogram distribution. + ///A linear interpolation is done within each bin + virtual void rnd_to_fct(float& valuex,float& valuey,float rnd, float rnd2) const { + size_t nbins=get_nbins(); + if(nbins==0) {valuex = 0.0; valuey = 0.0; return;} + Trandom residual_rnd; + size_t ibin=m_HistoContents.get_bin(rnd,residual_rnd); + + Trandom frac=m_HistoContents.get_fraction(ibin); + + size_t ibiny = ibin % m_HistoBordersy.get_nbins(); //printf("%d ", m_HistoBordersy.get_nbins() ); + size_t ibinx = ibin / m_HistoBordersy.get_nbins(); + //size_t nbinsx = m_HistoBordersx.get_nbins(); + size_t nbinsy = m_HistoBordersy.get_nbins(); + + Trandom dfrac; + auto l=m_HistoBordersy.GetBinLength(ibiny); + Trandom dfracprev; + auto lprev=l; + if(ibiny>0) { + Trandom fracprev=m_HistoContents.get_fraction(ibin-1); + dfrac=frac-fracprev; + if(ibiny>1) { + dfracprev=fracprev-m_HistoContents.get_fraction(ibin-2); + } else { + dfracprev=fracprev; + if(ibinx>0) dfracprev-=m_HistoContents.get_fraction(ibin-2); + } + lprev=m_HistoBordersy.GetBinLength(ibiny-1); + } else { + dfrac=frac; + if(ibinx>0) dfrac-=m_HistoContents.get_fraction(ibin-1); + dfracprev=dfrac; + } + + Trandom dfracnext; + auto lnext=l; + if(ibiny<nbinsy-1) { + dfracnext=m_HistoContents.get_fraction(ibin+1)-frac; + lnext=m_HistoBordersy.GetBinLength(ibiny+1); + } else { + dfracnext=dfrac; + } + + Trandom m; + if(dfrac>0) { + Trandom mnext=dfracnext/lnext-dfrac/l; + mnext/=l+lnext; + Trandom mprev=dfrac/l-dfracprev/lprev; + mprev/=l+lprev; + m=(mnext+mprev)*l*l/dfrac; + } else m=0; + + valuey = m_HistoBordersy.position(ibiny,m,residual_rnd); + valuex = m_HistoBordersx.position(ibinx, rnd2); + } + + ClassDef(TFCS2DFunctionTemplateInterpolationHistogram,1) //TFCS1DFunctionTemplateInterpolationHistogram +}; + +class TFCS2DFunctionInt8Int8Int8InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float> +{ + public: + TFCS2DFunctionInt8Int8Int8InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint8_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int8Int8InterpolationHistogram,1) //TFCS2DFunctionInt8Int8Int8InterpolationHistogram +}; + +class TFCS2DFunctionInt8Int8Int16InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float> +{ + public: + TFCS2DFunctionInt8Int8Int16InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint16_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int8Int16InterpolationHistogram,1) //TFCS2DFunctionInt8Int8Int16InterpolationHistogram +}; + +class TFCS2DFunctionInt8Int8Int32InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint32_t,float> +{ + public: + TFCS2DFunctionInt8Int8Int32InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt8BinEdges,uint32_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int8Int32InterpolationHistogram,1) //TFCS2DFunctionInt8Int8Int32InterpolationHistogram +}; + + + +class TFCS2DFunctionInt8Int16Int8InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint8_t,float> +{ + public: + TFCS2DFunctionInt8Int16Int8InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint8_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int16Int8InterpolationHistogram,1) //TFCS2DFunctionInt8Int16Int8InterpolationHistogram +}; + +class TFCS2DFunctionInt8Int16Int16InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float> +{ + public: + TFCS2DFunctionInt8Int16Int16InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int16Int16InterpolationHistogram,1) //TFCS2DFunctionInt8Int16Int16InterpolationHistogram +}; + +class TFCS2DFunctionInt8Int16Int32InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float> +{ + public: + TFCS2DFunctionInt8Int16Int32InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt8Int16Int32InterpolationHistogram,1) //TFCS2DFunctionInt8Int16Int32InterpolationHistogram +}; + + + +class TFCS2DFunctionInt16Int16Int8InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint8_t,float> +{ + public: + TFCS2DFunctionInt16Int16Int8InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint8_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt16Int16Int8InterpolationHistogram,1) //TFCS2DFunctionInt16Int16Int8InterpolationHistogram +}; + +class TFCS2DFunctionInt16Int16Int16InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float> +{ + public: + TFCS2DFunctionInt16Int16Int16InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint16_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt16Int16Int16InterpolationHistogram,1) //TFCS2DFunctionInt16Int16Int16InterpolationHistogram +}; + +class TFCS2DFunctionInt16Int16Int32InterpolationHistogram: public TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float> +{ + public: + TFCS2DFunctionInt16Int16Int32InterpolationHistogram(TH2* h=nullptr):TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges,TFCS1DFunction_HistogramInt16BinEdges,uint32_t,float>(h) {}; + + ClassDef(TFCS2DFunctionInt16Int16Int32InterpolationHistogram,1) //TFCS2DFunctionInt16Int16Int32InterpolationHistogram +}; + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt8BinEdges, uint32_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt8BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint32_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint8_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint16_t,float>+; +#pragma link C++ class TFCS2DFunctionTemplateInterpolationHistogram<TFCS1DFunction_HistogramInt16BinEdges, TFCS1DFunction_HistogramInt16BinEdges, uint32_t,float>+; + +#pragma link C++ class TFCS2DFunctionInt8Int8Int8InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt8Int8Int16InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt8Int8Int32InterpolationHistogram+; + +#pragma link C++ class TFCS2DFunctionInt8Int16Int8InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt8Int16Int16InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt8Int16Int32InterpolationHistogram+; + +#pragma link C++ class TFCS2DFunctionInt16Int16Int8InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt16Int16Int16InterpolationHistogram+; +#pragma link C++ class TFCS2DFunctionInt16Int16Int32InterpolationHistogram+; + +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSEnergyRenormalization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSEnergyRenormalization.h new file mode 100644 index 0000000000000000000000000000000000000000..47966d9d6d3482fcf89015ff65ba34cc43186024 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSEnergyRenormalization.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ISF_FASTCALOSIMEVENT_TFCSEnergyRenormalization_h +#define ISF_FASTCALOSIMEVENT_TFCSEnergyRenormalization_h + +#include "ISF_FastCaloSimEvent/TFCSParametrization.h" + +/** The class TFCSEnergyRenormalization ensures that the sum of cell energies in every calorimeter layer + matches the output of energy simulation +*/ + +class TFCSEnergyRenormalization:public TFCSParametrization { +public: + TFCSEnergyRenormalization(const char* name=nullptr, const char* title=nullptr); + virtual ~TFCSEnergyRenormalization(); + + virtual bool is_match_Ekin_bin(int /*Ekin_bin*/) const override; + virtual bool is_match_calosample(int /*calosample*/) const override; + + virtual FCSReturnCode simulate(TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) override; +private: + + ClassDefOverride(TFCSEnergyRenormalization,1) //TFCSEnergyRenormalization +}; + +inline bool TFCSEnergyRenormalization::is_match_Ekin_bin(int /*Ekin_bin*/) const +{ + return true; +} + +inline bool TFCSEnergyRenormalization::is_match_calosample(int /*calosample*/) const +{ + return true; +} + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCSEnergyRenormalization+; +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSFlatLateralShapeParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSFlatLateralShapeParametrization.h new file mode 100644 index 0000000000000000000000000000000000000000..fd516c4efd1f140c991296f6563f2b4ac4380580 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSFlatLateralShapeParametrization.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TFCSFlatLateralShapeParametrization_h +#define TFCSFlatLateralShapeParametrization_h + +#include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h" +#include "ISF_FastCaloSimEvent/TFCS2DFunctionHistogram.h" +#include "ISF_FastCaloSimEvent/TFCSTruthState.h" + +class TH2; + +class TFCSFlatLateralShapeParametrization:public TFCSLateralShapeParametrizationHitBase { +public: + TFCSFlatLateralShapeParametrization(const char* name=nullptr, const char* title=nullptr); + virtual ~TFCSFlatLateralShapeParametrization(); + + /// set the integral of the histogram to the desired number of hits + void set_number_of_hits(float nhits); + + float get_number_of_expected_hits() const; + + /// default for this class is to simulate poisson(integral histogram) hits + virtual int get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const override; + + /// set the radius in which hits should be generated + void set_dR(float _dR); + + float dR() const; + + /// set the radius in which hits should be generated + void set_scale(float _scale); + + float scale() const; + + /// simulated one hit position with weight that should be put into simulstate + /// sometime later all hit weights should be resacled such that their final sum is simulstate->E(sample) + /// someone also needs to map all hits into cells + virtual FCSReturnCode simulate_hit(Hit& hit,TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) override; + + virtual void Print(Option_t *option = "") const override; +protected: + /// Simulate hits flat in radius dR + float m_dR; + float m_nhits; + float m_scale; + +private: + + ClassDefOverride(TFCSFlatLateralShapeParametrization,1) //TFCSFlatLateralShapeParametrization +}; + +inline float TFCSFlatLateralShapeParametrization::get_number_of_expected_hits() const +{ + return m_nhits; +} + +inline float TFCSFlatLateralShapeParametrization::dR() const +{ + return m_dR; +} + +inline float TFCSFlatLateralShapeParametrization::scale() const +{ + return m_scale; +} + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCSFlatLateralShapeParametrization+; +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeParametrization.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeParametrization.h index f6ecbe2e4f6c615bb1aca035083733e7e6e00a85..50bd8fa5041efa9330e35e8195c1625f80b6fb84 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeParametrization.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeParametrization.h @@ -29,8 +29,20 @@ public: void set_number_of_hits(float nhits); float get_number_of_expected_hits() const {return m_nhits;}; + + ///set an offset in r on the simulated histogram + void set_r_offset(float r_offset) {m_r_offset=r_offset;}; + float r_offset() const {return m_r_offset;}; + + ///set an scale factor for r on the simulated histogram + void set_r_scale(float r_scale) {m_r_scale=r_scale;}; + float r_scale() const {return m_r_scale;}; + + ///default for this class is to simulate get_number_of_expected_hits() hits, + ///which gives fluctuations sigma^2=1/get_number_of_expected_hits() + virtual double get_sigma2_fluctuation(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const override; - /// default for this class is to simulate poisson(integral histogram) hits + /// default for this class is to simulate get_number_of_expected_hits() hits int get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const override; /// simulated one hit position with weight that should be put into simulstate @@ -50,10 +62,12 @@ protected: /// Histogram to be used for the shape simulation TFCS2DFunctionHistogram m_hist; float m_nhits; + float m_r_offset; + float m_r_scale; private: - ClassDefOverride(TFCSHistoLateralShapeParametrization,1) //TFCSHistoLateralShapeParametrization + ClassDefOverride(TFCSHistoLateralShapeParametrization,2) //TFCSHistoLateralShapeParametrization }; #if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeight.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeight.h new file mode 100644 index 0000000000000000000000000000000000000000..dc650c2ca08d400c17315eca14fb1d8eeebd6e1a --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeight.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TFCSHistoLateralShapeWeight_h +#define TFCSHistoLateralShapeWeight_h + +#include "ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h" + +class TH1; + +class TFCSHistoLateralShapeWeight:public TFCSLateralShapeParametrizationHitBase { +public: + TFCSHistoLateralShapeWeight(const char* name=nullptr, const char* title=nullptr); + virtual ~TFCSHistoLateralShapeWeight(); + + /// weight the energy of one hit in order to generate fluctuations + virtual FCSReturnCode simulate_hit(Hit& hit,TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) override; + + /// Init from histogram. The integral of the histogram is used as number of expected hits to be generated + bool Initialize(TH1* hist); + + virtual void Print(Option_t *option = "") const override; +protected: + /// Histogram to be used for the shape simulation + /// The histogram x-axis should be in dR^2=deta^2+dphi^2 + TH1* m_hist{nullptr}; + + ClassDefOverride(TFCSHistoLateralShapeWeight,1) //TFCSHistoLateralShapeWeight +}; + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCSHistoLateralShapeWeight+; +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeightHitAndMiss.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeightHitAndMiss.h new file mode 100644 index 0000000000000000000000000000000000000000..ebdce230bf4960dc0fb7dd0dba17c7d10b0c7ac2 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeightHitAndMiss.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TFCSHistoLateralShapeWeightHitAndMiss_h +#define TFCSHistoLateralShapeWeightHitAndMiss_h + +#include "ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeight.h" + +class TH1; + +class TFCSHistoLateralShapeWeightHitAndMiss:public TFCSHistoLateralShapeWeight { +public: + TFCSHistoLateralShapeWeightHitAndMiss(const char* name=nullptr, const char* title=nullptr); + virtual ~TFCSHistoLateralShapeWeightHitAndMiss(); + + /// weight the energy of one hit in order to generate fluctuations. If the hit energy is 0, discard the hit + virtual FCSReturnCode simulate_hit(Hit& hit,TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) override; + +private: + + ClassDefOverride(TFCSHistoLateralShapeWeightHitAndMiss,1) //TFCSHistoLateralShapeWeightHitAndMiss +}; + +#if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) +#pragma link C++ class TFCSHistoLateralShapeWeightHitAndMiss+; +#endif + +#endif diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHitCellMappingWiggle.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHitCellMappingWiggle.h index 59374d81bb3af36ef281911bdb811b10ddbe02f2..5804324671cb64db0fc57baf0f870c64adee111f 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHitCellMappingWiggle.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSHitCellMappingWiggle.h @@ -26,7 +26,7 @@ public: inline double get_bin_low_edge(int bin) const {return m_bin_low_edge[bin];}; inline double get_bin_up_edge(int bin) const {return m_bin_low_edge[bin+1];}; - inline const TFCS1DFunction* get_function(int bin) {return m_functions[bin];}; + inline const TFCS1DFunction* get_function(int bin) const {return m_functions[bin];}; const std::vector< const TFCS1DFunction* > get_functions() {return m_functions;}; const std::vector< float > get_bin_low_edges() {return m_bin_low_edge;}; diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h index 89f1c721aac2eb21c18b262ef184c25564d6e484..44635409f11c09d9d3bc5b98339d0d3a23f4aea8 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitBase.h @@ -13,7 +13,10 @@ class TFCSLateralShapeParametrizationHitBase:public TFCSLateralShapeParametrizat public: TFCSLateralShapeParametrizationHitBase(const char* name=nullptr, const char* title=nullptr); - ///Call get_number_of_hits() only once per shower simulation, as it could be calculated with random numbers and give different results each time + ///Give the effective size sigma^2 of the fluctuations that should be generated by the amount of generated hits. Return a value <0 if this instance can't determine + virtual double get_sigma2_fluctuation(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const; + + ///Call get_number_of_hits() only once per shower simulation, as it could be calculated with random numbers and give different results each time. Return a value of -1 if this instance can't determine virtual int get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const; class Hit @@ -38,6 +41,13 @@ public: m_useXYZ=true; } + inline void reset_center(){ + m_center_r=0; + m_center_z=0; + m_center_eta=0; + m_center_phi=0; + } + inline void reset(){ m_eta_x=0.; m_phi_y=0.; diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h index 4a912ace0c96c4d832a4fd45f0fb5a54b1b9111a..497e1e448ade5a8e83c80ed344ab8f2b3ddf2ef9 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitChain.h @@ -25,7 +25,10 @@ public: const Chain_t& chain() const {return m_chain;}; Chain_t& chain() {return m_chain;}; void push_back( const Chain_t::value_type& value ) {m_chain.push_back(value);}; - + //TODO: add generic functionality to determine the number of hits or center position only once + // and not for every iteration of the hit chain + + /// set which instance should determine the number of hits virtual void set_number_of_hits_simul(TFCSLateralShapeParametrizationHitBase* sim) {m_number_of_hits_simul=sim;}; /// Call get_number_of_hits() only once, as it could contain a random number diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitNumberFromE.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitNumberFromE.h index cbe0e39996096567ab2a9130c8647e5eb5a545bb..e43420da0ad2c14a0ee7c470118631db7ba7696a 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitNumberFromE.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSLateralShapeParametrizationHitNumberFromE.h @@ -26,6 +26,9 @@ public: /// constant=0.035; TFCSLateralShapeParametrizationHitNumberFromE(const char* name=nullptr, const char* title=nullptr,double stochastic=0.1,double constant=0); + ///Give the effective size sigma^2 of the fluctuations from the stochastic and constant term + double get_sigma2_fluctuation(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const override; + int get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const override; void Print(Option_t *option = "") const override; diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBase.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBase.h index 0ee503bffd36648a59a25ca1636bc27353cffc1e..9ac1b7cf1761ef1f4bca8f1b1401d2169f7dd8d5 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBase.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/ISF_FastCaloSimEvent/TFCSParametrizationBase.h @@ -141,12 +141,12 @@ public: static void DoCleanup(); protected: - const double init_Ekin_nominal=0; - const double init_Ekin_min=0; - const double init_Ekin_max=14000000; - const double init_eta_nominal=0; - const double init_eta_min=-100; - const double init_eta_max=100; + static constexpr double init_Ekin_nominal=0;//! Do not persistify! + static constexpr double init_Ekin_min=0;//! Do not persistify! + static constexpr double init_Ekin_max=14000000;//! Do not persistify! + static constexpr double init_eta_nominal=0;//! Do not persistify! + static constexpr double init_eta_min=-100;//! Do not persistify! + static constexpr double init_eta_max=100;//! Do not persistify! static std::vector< TFCSParametrizationBase* > s_cleanup_list; @@ -196,7 +196,7 @@ private: private: static std::set< int > s_no_pdgid; - ClassDef(TFCSParametrizationBase,1) //TFCSParametrizationBase + ClassDef(TFCSParametrizationBase,2) //TFCSParametrizationBase }; #if defined(__ROOTCLING__) && defined(__FastCaloSimStandAlone__) diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunction.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunction.cxx index 8a9ecda8a593b641822ec3dde9be0cf3bf92eadd..b53faf24a837d33aeb7ad4ddb38aae4d3ba7b8f2 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunction.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunction.cxx @@ -113,7 +113,7 @@ void TFCS1DFunction::unit_test(TH1* hist,TFCS1DFunction* rtof,int nrnd,TH1* hist std::cout<<"rnd0="<<rnd[0]<<" -> x="<<value[0]<<std::endl; } - TH1* hist_val; + TH1* hist_val=nullptr; if(histfine) hist_val=(TH1*)histfine->Clone(TString(hist->GetName())+"hist_val"); else hist_val=(TH1*)hist->Clone(TString(hist->GetName())+"hist_val"); double weightfine=hist_val->Integral()/nrnd; @@ -142,7 +142,6 @@ void TFCS1DFunction::unit_test(TH1* hist,TFCS1DFunction* rtof,int nrnd,TH1* hist float val=hist_diff->GetBinContent(ix); float err=hist_diff->GetBinError(ix); if(err>0) hist_pull->Fill(val/err); - //std::cout<<"x="<<hist->GetBinCenter(ix)<<" : pull val="<<val<<" err="<<err<<std::endl; } //Screen output in athena won't make sense and would require linking of additional libraries diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionInt32Histogram.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionInt32Histogram.cxx index 62fc8c186d65419f0c663e4db530316f1ae515af..1402bd4277fb76d4263bfe430679cb2e0cd9be65 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionInt32Histogram.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionInt32Histogram.cxx @@ -53,8 +53,7 @@ void TFCS1DFunctionInt32Histogram::Initialize(const TH1* hist) for(ibin=0;ibin<nbins;++ibin) { m_HistoContents[ibin]=s_MaxValue*(temp_HistoContents[ibin]/integral); - //std::cout<<"bin="<<ibin<<" val="<<m_HistoContents[ibin]<<std::endl; - } + } } double TFCS1DFunctionInt32Histogram::rnd_to_fct(double rnd) const diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateHelpers.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateHelpers.cxx new file mode 100644 index 0000000000000000000000000000000000000000..cd7bf32500b783e0afa0cc323836dcc30b96318c --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateHelpers.cxx @@ -0,0 +1,10 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ISF_FastCaloSimEvent/TFCS1DFunctionTemplateHelpers.h" + +//============================================= +//======= TFCS1DFunctionTemplateHelpers ========= +//============================================= + diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateHistogram.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateHistogram.cxx index 27273e697e30b73f529973ffb052cdaab853ce51..168353d57a93a918eb4866a1173822383e28a404 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateHistogram.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateHistogram.cxx @@ -7,4 +7,3 @@ //============================================= //======= TFCS1DFunctionTemplateHistogram ========= //============================================= - diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateInterpolationHistogram.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateInterpolationHistogram.cxx new file mode 100644 index 0000000000000000000000000000000000000000..12295ce68f2e549c5b184519736aee26691508a0 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS1DFunctionTemplateInterpolationHistogram.cxx @@ -0,0 +1,9 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ISF_FastCaloSimEvent/TFCS1DFunctionTemplateInterpolationHistogram.h" + +//============================================= +//======= TFCS1DFunctionTemplateInterpolationHistogram ========= +//============================================= diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunction.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunction.cxx index f657c8fd3f9849eea4a499cc13ceef6f6283bc55..e1cc3a6d1a3f43c04af837a5b2430dcdabd492b6 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunction.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunction.cxx @@ -3,6 +3,15 @@ */ #include "ISF_FastCaloSimEvent/TFCS2DFunction.h" +#include "ISF_FastCaloSimEvent/TFCS2DFunctionHistogram.h" +#include "ISF_FastCaloSimEvent/TFCS2DFunctionTemplateHistogram.h" +#include "TH2.h" +#include "TCanvas.h" +#include "TH2F.h" +#include "TRandom.h" +#include "TFile.h" + +#include <iostream> //============================================= //======= TFCS2DFunction ========= @@ -12,3 +21,138 @@ void TFCS2DFunction::rnd_to_fct(float value[],const float rnd[]) const { rnd_to_fct(value[0],value[1],rnd[0],rnd[1]); } + +//================================================================================================================================ + +double TFCS2DFunction::CheckAndIntegrate2DHistogram(const TH2* hist, std::vector<double>& integral_vec, int& first, int& last) +{ + Int_t nbinsx = hist->GetNbinsX(); + Int_t nbinsy = hist->GetNbinsY(); + Int_t nbins = nbinsx*nbinsy; + + float integral=0.0; + float hint = hist->Integral(); + integral_vec.resize(nbins); + + + for (int ix=1; ix<=nbinsx; ix++) { + for (int iy=1; iy<=nbinsy; iy++) { + int globalbin = (ix-1)*nbinsy + iy - 1; + float binval = hist->GetBinContent(ix,iy); + if(binval<0) { + //Can't work if a bin is negative, forcing bins to 0 in this case + double fraction=binval/hint; + if(TMath::Abs(fraction)>1e-5) { + std::cout<<"WARNING: bin content is negative in histogram "<<hist->GetName()<<" : "<<hist->GetTitle()<<" binval="<<binval<<" "<<fraction*100<<"% of integral="<<hist->Integral()<<". Forcing bin to 0."<<std::endl; + } + binval=0; + } + integral+=binval; + integral_vec[globalbin]=integral; + } + } + + for(first=0; first<nbins; first++) if(integral_vec[first]!=0) break; + for(last=nbins-1; last>0; last--) if(integral_vec[last]!=integral) break; + last++; + + if(integral<=0) { + std::cout<<"ERROR: histogram "<<hist->GetName()<<" : "<<hist->GetTitle()<<" integral="<<integral<<" is <=0"<<std::endl; + } + + return integral; +} + +TH2* create_random_TH2(int nbinsx=64,int nbinsy=64) +{ + TH2* hist=new TH2F("test2D","test2D",nbinsx,0,1,nbinsy,0,1); + hist->Sumw2(); + for(int ix=1;ix<=nbinsx;++ix) { + for(int iy=1;iy<=nbinsy;++iy) { + hist->SetBinContent(ix,iy,(0.5+gRandom->Rndm())*(nbinsx+ix)*(nbinsy*nbinsy/2+iy*iy)); + if(gRandom->Rndm()<0.1) hist->SetBinContent(ix,iy,0); + hist->SetBinError(ix,iy,0); + } + } + return hist; +} + +void TFCS2DFunction::unit_test(TH2* hist,TFCS2DFunction* rtof,const char* outfilename,int nrnd) +{ + if(hist==nullptr) hist=create_random_TH2(); + if(rtof==nullptr) rtof=new TFCS2DFunctionHistogram(hist); + + int nbinsx=hist->GetNbinsX(); + int nbinsy=hist->GetNbinsY(); + + float value[2]; + float rnd[2]; + for(rnd[0]=0;rnd[0]<0.9999;rnd[0]+=0.25) { + for(rnd[1]=0;rnd[1]<0.9999;rnd[1]+=0.25) { + rtof->rnd_to_fct(value,rnd); + std::cout<<"rnd0="<<rnd[0]<<" rnd1="<<rnd[1]<<" -> x="<<value[0]<<" y="<<value[1]<<std::endl; + } + } + +// TH2F* hist_val=new TH2F("val2D","val2D",16,hist->GetXaxis()->GetXmin(),hist->GetXaxis()->GetXmax(), +// 16,hist->GetYaxis()->GetXmin(),hist->GetYaxis()->GetXmax()); + TH2F* hist_val=(TH2F*)hist->Clone(TString(hist->GetName())+"_"+rtof->ClassName()); + hist_val->Reset(); + + float weight=hist->Integral()/nrnd; + hist_val->Sumw2(); + for(int i=0;i<nrnd;++i) { + rnd[0]=gRandom->Rndm(); + rnd[1]=gRandom->Rndm(); + rtof->rnd_to_fct(value,rnd); + hist_val->Fill(value[0],value[1],weight); + } + hist_val->Add(hist,-1); + + TH1F* hist_pull=new TH1F(TString("pull_")+rtof->ClassName(),TString("pull for ")+rtof->ClassName(),80,-4,4); + for(int ix=1;ix<=nbinsx;++ix) { + for(int iy=1;iy<=nbinsy;++iy) { + float val=hist_val->GetBinContent(ix,iy); + float err=hist_val->GetBinError(ix,iy); + if(err>0) hist_pull->Fill(val/err); + //std::cout<<"val="<<val<<" err="<<err<<std::endl; + } + } + + std::unique_ptr<TFile> outputfile(TFile::Open( outfilename, "UPDATE" )); + if (outputfile != NULL) { + hist->Write(); + hist_val->Write(); + hist_pull->Write(); + outputfile->ls(); + } + +//Screen output in athena won't make sense and would require linking of additional libraries +#if defined(__FastCaloSimStandAlone__) + new TCanvas(hist->GetName(),hist->GetTitle()); + hist->Draw("colz"); + + new TCanvas(hist_val->GetName(),hist_val->GetTitle()); + hist_val->Draw("colz"); + + new TCanvas(hist_pull->GetName(),hist_pull->GetTitle()); + hist_pull->Draw(); +#endif +} + +void TFCS2DFunction::unit_tests(TH2* hist,const char* outfilename,int nrnd) +{ + if(hist==nullptr) hist=create_random_TH2(16,16); + + const int ntest=4; + TFCS2DFunction* tests[ntest]; + tests[0]=new TFCS2DFunctionHistogram(hist); + tests[1]=new TFCS2DFunctionInt8Int8Int8Histogram(hist); + tests[2]=new TFCS2DFunctionInt8Int8Int16Histogram(hist); + tests[3]=new TFCS2DFunctionInt8Int8Int32Histogram(hist); + + for(int i=0;i<ntest;++i) { + unit_test(hist,tests[i],outfilename,nrnd); + } +} + diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionLateralShapeParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionLateralShapeParametrization.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3f555ab2f37163c927dfe0fa5fdddc6f367bc1ef --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionLateralShapeParametrization.cxx @@ -0,0 +1,150 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CLHEP/Random/RandFlat.h" +#include "CLHEP/Random/RandPoisson.h" + +#include "ISF_FastCaloSimEvent/TFCS2DFunctionLateralShapeParametrization.h" +#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h" +#include "ISF_FastCaloSimEvent/TFCSSimulationState.h" +#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h" + +#include "TFile.h" +#include "TMath.h" +#include "TH2.h" + +#include "HepPDT/ParticleData.hh" +#include "HepPDT/ParticleDataTable.hh" + +//============================================= +//======= TFCS2DFunctionLateralShapeParametrization ========= +//============================================= + +TFCS2DFunctionLateralShapeParametrization::TFCS2DFunctionLateralShapeParametrization(const char* name, const char* title) : + TFCSLateralShapeParametrizationHitBase(name,title),m_function(nullptr),m_nhits(0) +{ + reset_phi_symmetric(); +} + +TFCS2DFunctionLateralShapeParametrization::~TFCS2DFunctionLateralShapeParametrization() +{ + if(m_function) delete m_function; + m_function=nullptr; +} + +double TFCS2DFunctionLateralShapeParametrization::get_sigma2_fluctuation(TFCSSimulationState& /*simulstate*/,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const +{ + return 1.0/m_nhits; +} + +int TFCS2DFunctionLateralShapeParametrization::get_number_of_hits(TFCSSimulationState &simulstate, const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const +{ + if (!simulstate.randomEngine()) { + return -1; + } + + return CLHEP::RandPoisson::shoot(simulstate.randomEngine(), m_nhits); +} + +void TFCS2DFunctionLateralShapeParametrization::set_number_of_hits(float nhits) +{ + m_nhits=nhits; +} + +FCSReturnCode TFCS2DFunctionLateralShapeParametrization::simulate_hit(Hit &hit, TFCSSimulationState &simulstate, const TFCSTruthState* truth, const TFCSExtrapolationState* /*extrapol*/) +{ + if (!simulstate.randomEngine()) { + return FCSFatal; + } + if (!m_function) { + return FCSFatal; + } + + const int pdgId = truth->pdgid(); + const double charge = HepPDT::ParticleID(pdgId).charge(); + + const int cs=calosample(); + const double center_eta = hit.center_eta(); + const double center_phi = hit.center_phi(); + const double center_r = hit.center_r(); + const double center_z = hit.center_z(); + + if (TMath::IsNaN(center_r) or TMath::IsNaN(center_z) or TMath::IsNaN(center_eta) or TMath::IsNaN(center_phi)) { //Check if extrapolation fails + return FCSFatal; + } + + float alpha, r, rnd1, rnd2; + rnd1 = CLHEP::RandFlat::shoot(simulstate.randomEngine()); + rnd2 = CLHEP::RandFlat::shoot(simulstate.randomEngine()); + if(is_phi_symmetric()) { + if(rnd2>=0.5) { //Fill negative phi half of shape + rnd2-=0.5; + rnd2*=2; + m_function->rnd_to_fct(alpha,r,rnd1,rnd2); + alpha=-alpha; + } else { //Fill positive phi half of shape + rnd2*=2; + m_function->rnd_to_fct(alpha,r,rnd1,rnd2); + } + } else { + m_function->rnd_to_fct(alpha,r,rnd1,rnd2); + } + if(TMath::IsNaN(alpha) || TMath::IsNaN(r)) { + ATH_MSG_ERROR(" 2D function, #hits="<<m_nhits<<" alpha="<<alpha<<" r="<<r<<" rnd1="<<rnd1<<" rnd2="<<rnd2); + alpha=0; + r=0.001; + + ATH_MSG_ERROR(" This error could probably be retried"); + return FCSFatal; + } + + float delta_eta_mm = r * cos(alpha); + float delta_phi_mm = r * sin(alpha); + + // Particles with negative eta are expected to have the same shape as those with positive eta after transformation: delta_eta --> -delta_eta + if(center_eta<0.)delta_eta_mm = -delta_eta_mm; + // Particle with negative charge are expected to have the same shape as positively charged particles after transformation: delta_phi --> -delta_phi + if(charge < 0.) delta_phi_mm = -delta_phi_mm; + + const float dist000 = TMath::Sqrt(center_r * center_r + center_z * center_z); + const float eta_jakobi = TMath::Abs(2.0 * TMath::Exp(-center_eta) / (1.0 + TMath::Exp(-2 * center_eta))); + + const float delta_eta = delta_eta_mm / eta_jakobi / dist000; + const float delta_phi = delta_phi_mm / center_r; + + hit.setEtaPhiZE(center_eta + delta_eta,center_phi + delta_phi,center_z, hit.E()); + + ATH_MSG_DEBUG("HIT: E="<<hit.E()<<" cs="<<cs<<" eta="<<hit.eta()<<" phi="<<hit.phi()<< " z="<<hit.z()<<" r="<<r<<" alpha="<<alpha); + + return FCSSuccess; +} + + +bool TFCS2DFunctionLateralShapeParametrization::Initialize(TFCS2DFunction* func,float nhits) +{ + if(!func) return false; + if(m_function) delete m_function; + m_function=func; + + if(nhits>0) set_number_of_hits(nhits); + + return true; +} + +void TFCS2DFunctionLateralShapeParametrization::Print(Option_t *option) const +{ + TString opt(option); + bool shortprint=opt.Index("short")>=0; + bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint); + TString optprint=opt;optprint.ReplaceAll("short",""); + TFCSLateralShapeParametrizationHitBase::Print(option); + + if(longprint) { + if(is_phi_symmetric()) { + ATH_MSG_INFO(optprint <<" 2D function, #hits="<<m_nhits<<" (phi symmetric)"); + } else { + ATH_MSG_INFO(optprint <<" 2D function, #hits="<<m_nhits<<" (not phi symmetric)"); + } + } +} diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionTemplateHistogram.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionTemplateHistogram.cxx new file mode 100644 index 0000000000000000000000000000000000000000..bd33fd5b6de273fb74166fe66405d56d81782dbb --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionTemplateHistogram.cxx @@ -0,0 +1,10 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ISF_FastCaloSimEvent/TFCS2DFunctionTemplateHistogram.h" + +//============================================= +//======= TFCS2DFunctionTemplateHistogram ========= +//============================================= + diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionTemplateInterpolationHistogram.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionTemplateInterpolationHistogram.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c6ac1716666233a91cb4e2790d84c468d9dd9815 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCS2DFunctionTemplateInterpolationHistogram.cxx @@ -0,0 +1,10 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ISF_FastCaloSimEvent/TFCS2DFunctionTemplateInterpolationHistogram.h" + +//============================================= +//======= TFCS2DFunctionTemplateInterpolationHistogram ========= +//============================================= + diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSEnergyRenormalization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSEnergyRenormalization.cxx new file mode 100644 index 0000000000000000000000000000000000000000..daa099180361761fd5b151cb1fb5c44ac22a58cf --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSEnergyRenormalization.cxx @@ -0,0 +1,55 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "ISF_FastCaloSimEvent/TFCSEnergyRenormalization.h" +#include "ISF_FastCaloSimEvent/TFCSSimulationState.h" +#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h" +#include "CaloDetDescr/CaloDetDescrElement.h" + +//============================================= +//======= TFCSEnergyRenormalization ========= +//============================================= + +TFCSEnergyRenormalization::TFCSEnergyRenormalization(const char* name, const char* title):TFCSParametrization(name,title) +{ +} + +TFCSEnergyRenormalization::~TFCSEnergyRenormalization() +{ +} + +FCSReturnCode TFCSEnergyRenormalization::simulate(TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) +{ + std::vector< float > energies(CaloCell_ID_FCS::MaxSample,0); + + //Loop over all cells and sum up energies + for(const auto& iter : simulstate.cells()) { + const CaloDetDescrElement* theDDE=iter.first; + int layer=theDDE->getSampling(); + energies[layer]+=iter.second; + } + + std::vector< float > scalefactor(CaloCell_ID_FCS::MaxSample,1); + + for(int layer=0;layer<CaloCell_ID_FCS::MaxSample;++layer) { + if(energies[layer]!=0) scalefactor[layer]=simulstate.E(layer)/energies[layer]; + } + + //Loop over all cells and apply the scalefactor + for(auto& iter : simulstate.cells()) { + const CaloDetDescrElement* theDDE=iter.first; + int layer=theDDE->getSampling(); + iter.second*=scalefactor[layer]; + } + + if(msgLvl(MSG::DEBUG)) { + ATH_MSG_DEBUG("Apply scale factors : "); + for (int layer=0;layer<CaloCell_ID_FCS::MaxSample;++layer) { + ATH_MSG_DEBUG(" "<<layer<<" *= "<<scalefactor[layer]<<" : "<<energies[layer]<<" -> "<<simulstate.E(layer)); + } + } + + return FCSSuccess; +} + diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSFlatLateralShapeParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSFlatLateralShapeParametrization.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a84df0607ec92e269a7a43304deee3bb26c7708e --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSFlatLateralShapeParametrization.cxx @@ -0,0 +1,97 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CLHEP/Random/RandFlat.h" +#include "CLHEP/Random/RandPoisson.h" + +#include "ISF_FastCaloSimEvent/TFCSFlatLateralShapeParametrization.h" +#include "ISF_FastCaloSimEvent/FastCaloSim_CaloCell_ID.h" +#include "ISF_FastCaloSimEvent/TFCSSimulationState.h" +#include "ISF_FastCaloSimEvent/TFCSExtrapolationState.h" + +#include "TFile.h" +#include "TMath.h" +#include "TH2.h" + +//============================================= +//======= TFCSFlatLateralShapeParametrization ========= +//============================================= + +TFCSFlatLateralShapeParametrization::TFCSFlatLateralShapeParametrization(const char* name, const char* title) : + TFCSLateralShapeParametrizationHitBase(name,title),m_nhits(0),m_scale(1) +{ +} + +TFCSFlatLateralShapeParametrization::~TFCSFlatLateralShapeParametrization() +{ +} + +int TFCSFlatLateralShapeParametrization::get_number_of_hits(TFCSSimulationState &simulstate, const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const +{ + if (!simulstate.randomEngine()) { + return -1; + } + + return CLHEP::RandPoisson::shoot(simulstate.randomEngine(), m_nhits); +} + +void TFCSFlatLateralShapeParametrization::set_number_of_hits(float nhits) +{ + m_nhits=nhits; +} + +void TFCSFlatLateralShapeParametrization::set_dR(float _dR) +{ + m_dR=_dR; +} + +void TFCSFlatLateralShapeParametrization::set_scale(float _scale) +{ + m_scale=_scale; +} + +FCSReturnCode TFCSFlatLateralShapeParametrization::simulate_hit(Hit &hit, TFCSSimulationState &simulstate, const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) +{ + if (!simulstate.randomEngine()) { + return FCSFatal; + } + + const int cs=calosample(); + const double center_eta = hit.center_eta(); + const double center_phi = hit.center_phi(); + const double center_r = hit.center_r(); + const double center_z = hit.center_z(); + + if (TMath::IsNaN(center_r) or TMath::IsNaN(center_z) or TMath::IsNaN(center_eta) or TMath::IsNaN(center_phi)) { //Check if extrapolation fails + return FCSFatal; + } + + float alpha, r; + + alpha=2*TMath::Pi()*CLHEP::RandFlat::shoot(simulstate.randomEngine()); + r=m_dR*CLHEP::RandFlat::shoot(simulstate.randomEngine()); + + float delta_eta = r*cos(alpha); + float delta_phi = r*sin(alpha); + + hit.setEtaPhiZE(center_eta + delta_eta,center_phi + delta_phi,center_z, hit.E()*m_scale); + + ATH_MSG_DEBUG("HIT: E="<<hit.E()<<" cs="<<cs<<" eta="<<hit.eta()<<" phi="<<hit.phi()<< " z="<<hit.z()<<" r="<<r<<" alpha="<<alpha); + + return FCSSuccess; +} + + +void TFCSFlatLateralShapeParametrization::Print(Option_t *option) const +{ + TString opt(option); + bool shortprint=opt.Index("short")>=0; + bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint); + TString optprint=opt;optprint.ReplaceAll("short",""); + TFCSLateralShapeParametrizationHitBase::Print(option); + + if(longprint) { + ATH_MSG_INFO(optprint <<" dR="<<m_dR<<" scale factor="<<m_scale<<", #hits="<<m_nhits); + } +} diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeParametrization.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeParametrization.cxx index e7b62b40d5d01c535faa81a1fc7ba48fe7570121..860e87f933a8e7f5b9fd789ddfec14293661a336 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeParametrization.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeParametrization.cxx @@ -22,7 +22,7 @@ //============================================= TFCSHistoLateralShapeParametrization::TFCSHistoLateralShapeParametrization(const char* name, const char* title) : - TFCSLateralShapeParametrizationHitBase(name,title),m_nhits(0) + TFCSLateralShapeParametrizationHitBase(name,title),m_nhits(0),m_r_offset(0),m_r_scale(1.0) { reset_phi_symmetric(); } @@ -31,6 +31,13 @@ TFCSHistoLateralShapeParametrization::~TFCSHistoLateralShapeParametrization() { } +double TFCSHistoLateralShapeParametrization::get_sigma2_fluctuation(TFCSSimulationState& /*simulstate*/,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const +{ + //Limit to factor 1000 fluctuations + if(m_nhits<0.001) return 1000; + return 1.0/m_nhits; +} + int TFCSHistoLateralShapeParametrization::get_number_of_hits(TFCSSimulationState &simulstate, const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const { if (!simulstate.randomEngine()) { @@ -91,6 +98,9 @@ FCSReturnCode TFCSHistoLateralShapeParametrization::simulate_hit(Hit &hit, TFCSS return FCSFatal; } + r*=m_r_scale; + r+=m_r_offset; + if(r<0) r=0; float delta_eta_mm = r * cos(alpha); float delta_phi_mm = r * sin(alpha); @@ -152,9 +162,9 @@ void TFCSHistoLateralShapeParametrization::Print(Option_t *option) const if(longprint) { if(is_phi_symmetric()) { - ATH_MSG_INFO(optprint <<" Histo: "<<m_hist.get_HistoBordersx().size()-1<<"*"<<m_hist.get_HistoBordersy().size()-1<<" bins, #hits="<<m_nhits<<" (phi symmetric)"); + ATH_MSG_INFO(optprint <<" Histo: "<<m_hist.get_HistoBordersx().size()-1<<"*"<<m_hist.get_HistoBordersy().size()-1<<" bins, #hits="<<m_nhits<<", r scale="<<m_r_scale<<", r offset="<<m_r_offset<<"mm (phi symmetric)"); } else { - ATH_MSG_INFO(optprint <<" Histo: "<<m_hist.get_HistoBordersx().size()-1<<"*"<<m_hist.get_HistoBordersy().size()-1<<" bins, #hits="<<m_nhits<<" (not phi symmetric)"); + ATH_MSG_INFO(optprint <<" Histo: "<<m_hist.get_HistoBordersx().size()-1<<"*"<<m_hist.get_HistoBordersy().size()-1<<" bins, #hits="<<m_nhits<<", r scale="<<m_r_scale<<", r offset="<<m_r_offset<<"mm (not phi symmetric)"); } } } diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeWeight.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeWeight.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8700119c028761ab11bcbd527654b65d104f2be3 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeWeight.cxx @@ -0,0 +1,84 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CLHEP/Random/RandFlat.h" + +#include "ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeight.h" +#include "ISF_FastCaloSimEvent/TFCSSimulationState.h" + +#include "TH1.h" +#include "TVector2.h" +#include "TMath.h" + +//============================================= +//======= TFCSHistoLateralShapeWeight ========= +//============================================= + +TFCSHistoLateralShapeWeight::TFCSHistoLateralShapeWeight(const char* name, const char* title) : + TFCSLateralShapeParametrizationHitBase(name,title) +{ +} + +TFCSHistoLateralShapeWeight::~TFCSHistoLateralShapeWeight() +{ + if(m_hist) delete m_hist; +} + +FCSReturnCode TFCSHistoLateralShapeWeight::simulate_hit(Hit& hit,TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) +{ + if (!simulstate.randomEngine()) { + return FCSFatal; + } + + const double center_eta = hit.center_eta(); + const double center_phi = hit.center_phi(); + const double center_r = hit.center_r(); + const double center_z = hit.center_z(); + + const float dist000 = TMath::Sqrt(center_r * center_r + center_z * center_z); + const float eta_jakobi = TMath::Abs(2.0 * TMath::Exp(-center_eta) / (1.0 + TMath::Exp(-2 * center_eta))); + + const float delta_eta = hit.eta()-center_eta; + const float delta_phi = hit.phi()-center_phi; + const float delta_eta_mm = delta_eta * eta_jakobi * dist000; + const float delta_phi_mm = delta_phi * center_r; + const float delta_r_mm = TMath::Sqrt(delta_eta_mm*delta_eta_mm+delta_phi_mm*delta_phi_mm); + + //TODO: delta_r_mm should perhaps be cached in hit + + Int_t bin=m_hist->FindBin(delta_r_mm); + if(bin<1) bin=1; + if(bin>m_hist->GetNbinsX()) bin=m_hist->GetNbinsX(); + float weight=m_hist->GetBinContent(bin); + hit.E()*=weight; + + ATH_MSG_DEBUG("HIT: E="<<hit.E()<<" dR_mm="<<delta_r_mm<<" weight="<<weight); + return FCSSuccess; +} + + +bool TFCSHistoLateralShapeWeight::Initialize(TH1* hist) +{ + if(!hist) return false; + if(m_hist) delete m_hist; + m_hist=(TH1*)hist->Clone(TString("TFCSHistoLateralShapeWeight_")+hist->GetName()); + m_hist->SetDirectory(0); + + return true; +} + +void TFCSHistoLateralShapeWeight::Print(Option_t *option) const +{ + TString opt(option); + bool shortprint=opt.Index("short")>=0; + bool longprint=msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint); + TString optprint=opt;optprint.ReplaceAll("short",""); + TFCSLateralShapeParametrizationHitBase::Print(option); + + if(longprint) { + if(m_hist) ATH_MSG_INFO(optprint <<" Histogram: "<<m_hist->GetNbinsX()<<" bins ["<<m_hist->GetXaxis()->GetXmin()<<","<<m_hist->GetXaxis()->GetXmax()<<"]"); + else ATH_MSG_INFO(optprint <<" no Histogram"); + } +} + diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeWeightHitAndMiss.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeWeightHitAndMiss.cxx new file mode 100644 index 0000000000000000000000000000000000000000..63726341a0873ad01ff03543e61c4dcde2e354a8 --- /dev/null +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHistoLateralShapeWeightHitAndMiss.cxx @@ -0,0 +1,69 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CLHEP/Random/RandFlat.h" + +#include "ISF_FastCaloSimEvent/TFCSHistoLateralShapeWeightHitAndMiss.h" +#include "ISF_FastCaloSimEvent/TFCSSimulationState.h" + +#include "TH1.h" +#include "TVector2.h" +#include "TMath.h" + +//============================================= +//======= TFCSHistoLateralShapeWeightHitAndMiss ========= +//============================================= + +TFCSHistoLateralShapeWeightHitAndMiss::TFCSHistoLateralShapeWeightHitAndMiss(const char* name, const char* title):TFCSHistoLateralShapeWeight(name,title) +{ +} + +TFCSHistoLateralShapeWeightHitAndMiss::~TFCSHistoLateralShapeWeightHitAndMiss() +{ +} + +FCSReturnCode TFCSHistoLateralShapeWeightHitAndMiss::simulate_hit(Hit& hit,TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) +{ + if (!simulstate.randomEngine()) { + return FCSFatal; + } + + const double center_eta = hit.center_eta(); + const double center_phi = hit.center_phi(); + const double center_r = hit.center_r(); + const double center_z = hit.center_z(); + + const float dist000 = TMath::Sqrt(center_r * center_r + center_z * center_z); + const float eta_jakobi = TMath::Abs(2.0 * TMath::Exp(-center_eta) / (1.0 + TMath::Exp(-2 * center_eta))); + + const float delta_eta = hit.eta()-center_eta; + const float delta_phi = hit.phi()-center_phi; + const float delta_eta_mm = delta_eta * eta_jakobi * dist000; + const float delta_phi_mm = delta_phi * center_r; + const float delta_r_mm = TMath::Sqrt(delta_eta_mm*delta_eta_mm+delta_phi_mm*delta_phi_mm); + + //TODO: delta_r_mm should perhaps be cached in hit + + Int_t bin=m_hist->FindBin(delta_r_mm); + if(bin<1) bin=1; + if(bin>m_hist->GetNbinsX()) bin=m_hist->GetNbinsX(); + float weight=m_hist->GetBinContent(bin); + if(weight<=1) { + //if weight<=1, give lower energy to hit. + //TFCSLateralShapeParametrizationHitChain needs to be able to generate more hits in this case + hit.E()*=weight; + } else { + //if weight>1, accept only 1/weight events, but give them a higher energy increased by weight. + //This leads to larger fluctuations, while keeping the shape unchanged. + float prob=1.0/weight; + float rnd=CLHEP::RandFlat::shoot(simulstate.randomEngine()); + if(rnd<prob) hit.E()*=weight; + else hit.E()=0; + } + + ATH_MSG_DEBUG("HIT: E="<<hit.E()<<" dR_mm="<<delta_r_mm<<" weight="<<weight); + return FCSSuccess; +} + + diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMappingWiggle.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMappingWiggle.cxx index 72136bb2ac19d8a2412822a3b36f24d28d7511ae..94a6db4f3eca14c3d096f26c720b47f0154980d4 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMappingWiggle.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSHitCellMappingWiggle.cxx @@ -47,7 +47,7 @@ void TFCSHitCellMappingWiggle::initialize(TFCS1DFunction* func) void TFCSHitCellMappingWiggle::initialize(const std::vector< const TFCS1DFunction* >& functions, const std::vector< float >& bin_low_edges) { if(functions.size()+1!=bin_low_edges.size()) { - ATH_MSG_ERROR("Using "<<functions.size()<<" functions needs "<<functions.size()+1<<" bins, but got "<<bin_low_edges.size()<<"bins"); + ATH_MSG_ERROR("Using "<<functions.size()<<" functions needs "<<functions.size()+1<<" bin low edges, but got "<<bin_low_edges.size()<<"bins"); return; } for(auto function : m_functions) if(function) delete function; @@ -125,9 +125,9 @@ void TFCSHitCellMappingWiggle::Print(Option_t *option) const TString optprint=opt;optprint.ReplaceAll("short",""); if(longprint) { - ATH_MSG(INFO) << optprint <<" "<<get_number_of_bins()<<" functions in ["; - for (unsigned int i=0;i<get_number_of_bins();++i) msg()<<get_bin_low_edge(i)<<", "; - msg()<<get_bin_up_edge(get_number_of_bins()-1)<<"]"<< endmsg; + ATH_MSG(INFO) << optprint <<" "<<get_number_of_bins()<<" functions : "; + for (unsigned int i=0;i<get_number_of_bins();++i) msg()<<get_bin_low_edge(i)<<" < ("<<get_function(i)<<") < "; + msg()<<get_bin_up_edge(get_number_of_bins()-1)<< endmsg; } } diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitBase.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitBase.cxx index ace709d6cc37beff91c039906f7a6ea15db0fe88..8e2badda702e5ace27a7c1bd36ed34f75adadfc5 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitBase.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitBase.cxx @@ -16,6 +16,11 @@ TFCSLateralShapeParametrizationHitBase::TFCSLateralShapeParametrizationHitBase(c { } +double TFCSLateralShapeParametrizationHitBase::get_sigma2_fluctuation(TFCSSimulationState& /*simulstate*/,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const +{ + return -1; +} + int TFCSLateralShapeParametrizationHitBase::get_number_of_hits(TFCSSimulationState& /*simulstate*/,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const { return -1; diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitChain.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitChain.cxx index 7e3e400a63bb1a052c92b8d8e7956a56a40c0894..409255c124ebc741077af603fb7ed84a7a1f9ad7 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitChain.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitChain.cxx @@ -52,38 +52,52 @@ FCSReturnCode TFCSLateralShapeParametrizationHitChain::simulate(TFCSSimulationSt return FCSFatal; } - float Ehit=simulstate.E(calosample())/nhit; + float Elayer=simulstate.E(calosample()); + float Ehit=Elayer/nhit; + float sumEhit=0; bool debug = msgLvl(MSG::DEBUG); if (debug) { - ATH_MSG_DEBUG("E("<<calosample()<<")="<<simulstate.E(calosample())<<" #hits="<<nhit); + ATH_MSG_DEBUG("E("<<calosample()<<")="<<simulstate.E(calosample())<<" #hits~"<<nhit); } - for (int i = 0; i < nhit; ++i) { - TFCSLateralShapeParametrizationHitBase::Hit hit; + int ihit=0; + TFCSLateralShapeParametrizationHitBase::Hit hit; + hit.reset_center(); + do { + hit.reset(); hit.E()=Ehit; for(TFCSLateralShapeParametrizationHitBase* hitsim : m_chain) { if (debug) { - if (i < 2) hitsim->setLevel(MSG::DEBUG); + if (ihit < 2) hitsim->setLevel(MSG::DEBUG); else hitsim->setLevel(MSG::INFO); } for (int i = 0; i <= FCS_RETRY_COUNT; i++) { + //TODO: potentially change logic in case of a retry to redo the whole hit chain from an empty hit instead of just redoing one step in the hit chain if (i > 0) ATH_MSG_WARNING("TFCSLateralShapeParametrizationHitChain::simulate(): Retry simulate_hit call " << i << "/" << FCS_RETRY_COUNT); FCSReturnCode status = hitsim->simulate_hit(hit, simulstate, truth, extrapol); - if (status == FCSSuccess) + if (status == FCSSuccess) { + if(sumEhit+hit.E()>Elayer) hit.E()=Elayer-sumEhit;//sum of all hit energies needs to be Elayer: correct last hit accordingly break; - else if (status == FCSFatal) - return FCSFatal; + } else { + if (status == FCSFatal) return FCSFatal; + } if (i == FCS_RETRY_COUNT) { ATH_MSG_ERROR("TFCSLateralShapeParametrizationHitChain::simulate(): simulate_hit call failed after " << FCS_RETRY_COUNT << "retries"); } } } - } + sumEhit+=hit.E(); + ++ihit; + if(ihit>10*nhit) { + ATH_MSG_WARNING("TFCSLateralShapeParametrizationHitChain::simulate(): aborting hit chain, iterated " << 10*nhit << " times, expected " << nhit<<" times. Deposited E("<<calosample()<<")="<<sumEhit); + break; + } + } while (sumEhit<Elayer); return FCSSuccess; } diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitNumberFromE.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitNumberFromE.cxx index 55a3ddf360baab2d91608d45c7623fa368373dd2..6d48a5a7601f0165669727c7318b965470dd0375 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitNumberFromE.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimEvent/src/TFCSLateralShapeParametrizationHitNumberFromE.cxx @@ -19,12 +19,8 @@ TFCSLateralShapeParametrizationHitNumberFromE::TFCSLateralShapeParametrizationHi set_match_all_pdgid(); } -int TFCSLateralShapeParametrizationHitNumberFromE::get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const +double TFCSLateralShapeParametrizationHitNumberFromE::get_sigma2_fluctuation(TFCSSimulationState& simulstate,const TFCSTruthState* /*truth*/, const TFCSExtrapolationState* /*extrapol*/) const { - if (!simulstate.randomEngine()) { - return -1; - } - int cs=calosample(); double energy=simulstate.E(cs); @@ -38,7 +34,21 @@ int TFCSLateralShapeParametrizationHitNumberFromE::get_number_of_hits(TFCSSimula } double sigma_stochastic=m_stochastic/sqrt(energy/1000.0); - int hits = CLHEP::RandPoisson::shoot(simulstate.randomEngine(), 1.0 / (sigma_stochastic*sigma_stochastic + m_constant*m_constant)); + double sigma2 = sigma_stochastic*sigma_stochastic + m_constant*m_constant; + + ATH_MSG_DEBUG("sigma^2 fluctuation="<<sigma2); + + return sigma2; +} + +int TFCSLateralShapeParametrizationHitNumberFromE::get_number_of_hits(TFCSSimulationState& simulstate,const TFCSTruthState* truth, const TFCSExtrapolationState* extrapol) const +{ + if (!simulstate.randomEngine()) { + return -1; + } + + double sigma2=get_sigma2_fluctuation(simulstate,truth,extrapol); + int hits = CLHEP::RandPoisson::shoot(simulstate.randomEngine(), 1.0 / sigma2); ATH_MSG_DEBUG("#hits="<<hits); diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt index 8a185b740c7c967c00ba2719577c4263964ab3d6..3179d9f870795455eff3e26d481e2dc0c78d902e 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/CMakeLists.txt @@ -27,6 +27,8 @@ atlas_depends_on_subdirs( PUBLIC Calorimeter/CaloEvent Calorimeter/CaloIdentifier Calorimeter/CaloTrackingGeometry + Simulation/G4Sim/TrackRecord + Simulation/G4SimCnv/G4SimTPCnv Database/AthenaPOOL/AthenaPoolUtilities DetectorDescription/GeoModel/GeoAdaptors DetectorDescription/GeoModel/GeoModelInterfaces @@ -61,7 +63,7 @@ atlas_add_root_dictionary( ISF_FastCaloSimParametrizationLib ISF_FastCaloSimParametrization/TreeReader.h ISF_FastCaloSimParametrization/FCS_Cell.h ISF_FastCaloSimParametrization/CaloGeometry.h - ISF_FastCaloSimParametrization/CaloGeometryLookup.h + ISF_FastCaloSimParametrization/CaloGeometryLookup.h Root/LinkDef.h EXTERNAL_PACKAGES ROOT HepPDT XercesC CLHEP HepMC Geant4 ) diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ISF_HitAnalysis.h b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ISF_HitAnalysis.h index 3cc869ae945c75240bccf0f72a741cf539474419..accc9cc1a72f476018b97db8801496011b36366c 100755 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ISF_HitAnalysis.h +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/ISF_FastCaloSimParametrization/ISF_HitAnalysis.h @@ -195,6 +195,16 @@ class ISF_HitAnalysis : public AthAlgorithm { std::vector<float>* m_newTTC_Angle3D; std::vector<float>* m_newTTC_AngleEta; + + std::vector<float>* m_MuonEntryLayer_E; + std::vector<float>* m_MuonEntryLayer_px; + std::vector<float>* m_MuonEntryLayer_py; + std::vector<float>* m_MuonEntryLayer_pz; + std::vector<float>* m_MuonEntryLayer_x; + std::vector<float>* m_MuonEntryLayer_y; + std::vector<float>* m_MuonEntryLayer_z; + std::vector<int>* m_MuonEntryLayer_pdg; + /** The new Extrapolator setup */ ToolHandle<Trk::ITimedExtrapolator> m_extrapolator; ToolHandle<ICaloSurfaceHelper> m_caloSurfaceHelper; diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx index d94aa5036613b41718f94149917b5c9e17d8bede..e4c330305ba2b354053ee98885dcf9c6e3f4fdf4 100755 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/src/ISF_HitAnalysis.cxx @@ -26,6 +26,9 @@ #include "TileSimEvent/TileHit.h" #include "TileSimEvent/TileHitVector.h" +//Track Record +#include "TrackRecord/TrackRecordCollection.h" + //CaloCell #include "CaloEvent/CaloCellContainer.h" @@ -163,6 +166,15 @@ ISF_HitAnalysis::ISF_HitAnalysis(const std::string& name, ISvcLocator* pSvcLocat , m_newTTC_Angle3D(0) , m_newTTC_AngleEta(0) + , m_MuonEntryLayer_E(0) + , m_MuonEntryLayer_px(0) + , m_MuonEntryLayer_py(0) + , m_MuonEntryLayer_pz(0) + , m_MuonEntryLayer_x(0) + , m_MuonEntryLayer_y(0) + , m_MuonEntryLayer_z(0) + , m_MuonEntryLayer_pdg(0) + , m_caloEntrance(0) , m_calo_tb_coord(0) , m_sample_calo_surf(CaloCell_ID_FCS::noSample) @@ -546,6 +558,16 @@ StatusCode ISF_HitAnalysis::initialize() m_newTTC_Angle3D = new std::vector<float>; m_newTTC_AngleEta = new std::vector<float>; + m_MuonEntryLayer_E = new std::vector<float>; + m_MuonEntryLayer_px = new std::vector<float>; + m_MuonEntryLayer_py = new std::vector<float>; + m_MuonEntryLayer_pz = new std::vector<float>; + m_MuonEntryLayer_x = new std::vector<float>; + m_MuonEntryLayer_y = new std::vector<float>; + m_MuonEntryLayer_z = new std::vector<float>; + m_MuonEntryLayer_pdg = new std::vector<int>; + + // Optional branches if(m_saveAllBranches){ m_tree->Branch("HitX", &m_hit_x); @@ -637,6 +659,18 @@ StatusCode ISF_HitAnalysis::initialize() m_tree->Branch("newTTC_Angle3D",&m_newTTC_Angle3D); m_tree->Branch("newTTC_AngleEta",&m_newTTC_AngleEta); + + + m_tree->Branch("MuonEntryLayer_E",&m_MuonEntryLayer_E); + m_tree->Branch("MuonEntryLayer_px",&m_MuonEntryLayer_px); + m_tree->Branch("MuonEntryLayer_py",&m_MuonEntryLayer_py); + m_tree->Branch("MuonEntryLayer_pz",&m_MuonEntryLayer_pz); + m_tree->Branch("MuonEntryLayer_x",&m_MuonEntryLayer_x); + m_tree->Branch("MuonEntryLayer_y",&m_MuonEntryLayer_y); + m_tree->Branch("MuonEntryLayer_z",&m_MuonEntryLayer_z); + m_tree->Branch("MuonEntryLayer_pdg",&m_MuonEntryLayer_pdg); + + } dummyFile->Close(); return StatusCode::SUCCESS; @@ -833,6 +867,16 @@ StatusCode ISF_HitAnalysis::execute() m_newTTC_IDCaloBoundary_z->clear(); m_newTTC_Angle3D->clear(); m_newTTC_AngleEta->clear(); + + + m_MuonEntryLayer_E->clear(); + m_MuonEntryLayer_x->clear(); + m_MuonEntryLayer_y->clear(); + m_MuonEntryLayer_z->clear(); + m_MuonEntryLayer_px->clear(); + m_MuonEntryLayer_py->clear(); + m_MuonEntryLayer_pz->clear(); + //########################## //Get the FastCaloSim step info collection from store @@ -1083,6 +1127,30 @@ StatusCode ISF_HitAnalysis::execute() } //mcEvent }//truth event + + + //Retrieve and save MuonEntryLayer information + const TrackRecordCollection *MuonEntry = nullptr; + ATH_CHECK(evtStore()->retrieve(MuonEntry, "MuonEntryLayer")); + if (sc.isFailure()) + { + ATH_MSG_WARNING( "Couldn't read MuonEntry from StoreGate"); + //return NULL; + } + else{ + for ( const TrackRecord &record : *MuonEntry){ + m_MuonEntryLayer_E->push_back((record).GetEnergy()); + m_MuonEntryLayer_px->push_back((record).GetMomentum().getX()); + m_MuonEntryLayer_py->push_back((record).GetMomentum().getY()); + m_MuonEntryLayer_pz->push_back((record).GetMomentum().getZ()); + m_MuonEntryLayer_x->push_back((record).GetPosition().getX()); + m_MuonEntryLayer_y->push_back((record).GetPosition().getY()); + m_MuonEntryLayer_z->push_back((record).GetPosition().getZ()); + m_MuonEntryLayer_pdg->push_back((record).GetPDGCode()); + } + } + + //Get reco cells if available const CaloCellContainer *cellColl = 0; sc = evtStore()->retrieve(cellColl, "AllCalo"); diff --git a/Simulation/ISF/ISF_HepMC/ISF_HepMC_Tools/src/GenParticleSimWhiteList.cxx b/Simulation/ISF/ISF_HepMC/ISF_HepMC_Tools/src/GenParticleSimWhiteList.cxx index 04f55760e26d3de5ef6c5cb3fcadf7e10e7adee2..b75e219631f7d2008d607a59b8da5157d2587928 100644 --- a/Simulation/ISF/ISF_HepMC/ISF_HepMC_Tools/src/GenParticleSimWhiteList.cxx +++ b/Simulation/ISF/ISF_HepMC/ISF_HepMC_Tools/src/GenParticleSimWhiteList.cxx @@ -68,6 +68,9 @@ StatusCode ISF::GenParticleSimWhiteList::initialize() /** passes through to the private version of the filter */ bool ISF::GenParticleSimWhiteList::pass(const HepMC::GenParticle& particle) const { + + ATH_MSG_VERBOSE( "Checking whether " << particle << " passes the filter." ); + static std::vector<int> vertices(500); vertices.clear(); bool so_far_so_good = pass( particle , vertices ); @@ -81,6 +84,8 @@ bool ISF::GenParticleSimWhiteList::pass(const HepMC::GenParticle& particle) cons // Check this particle vertices.clear(); bool parent_all_clear = pass( **it , vertices ); + ATH_MSG_VERBOSE( "Parent all clear: " << parent_all_clear << + "\nIf true, will not pass the daughter because it should have been picked up through the parent already (to avoid multi-counting)." ); so_far_so_good = so_far_so_good && !parent_all_clear; } // Loop over parents } // particle had parents @@ -95,7 +100,6 @@ bool ISF::GenParticleSimWhiteList::pass(const HepMC::GenParticle& particle , std bool passFilter = std::binary_search( m_pdgId.begin() , m_pdgId.end() , particle.pdg_id() ) || MC::PID::isNucleus( particle.pdg_id() ); // Remove documentation particles passFilter = passFilter && particle.status()!=3; - // Test all daughter particles if (particle.end_vertex() && m_qs && passFilter){ // Break loops @@ -104,7 +108,10 @@ bool ISF::GenParticleSimWhiteList::pass(const HepMC::GenParticle& particle , std for (HepMC::GenVertex::particle_iterator it = particle.end_vertex()->particles_begin(HepMC::children); it != particle.end_vertex()->particles_end(HepMC::children); ++it){ passFilter = passFilter && pass( **it , used_vertices ); - if (!passFilter) break; + if (!passFilter) { + ATH_MSG_VERBOSE( "Daughter particle " << **it << " does not pass." ); + break; + } } // Loop over daughters } // Break loops } // particle had daughters diff --git a/Simulation/Tests/DigitizationTests/test/test_Digi_tf_mc15_2015_heavy_ion.sh b/Simulation/Tests/DigitizationTests/test/test_Digi_tf_mc15_2015_heavy_ion.sh new file mode 100755 index 0000000000000000000000000000000000000000..f5a27bc056ce6234891550fc987cc7cb6c1e3ece --- /dev/null +++ b/Simulation/Tests/DigitizationTests/test/test_Digi_tf_mc15_2015_heavy_ion.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# art-description: Run digitization combining a heavy ion sample produced with MC15 using 2015 geometry and conditions with Zmumu events +# art-include: 21.0/Athena +# art-include: 21.3/Athena +# art-include: 21.9/Athena +# art-include: master/Athena +# art-type: grid +# art-output: mc15_2015_heavyIon.RDO.pool.root + +DigiOutFileName="mc15_2015_heavyIon.RDO.pool.root" +ZmumuHITSFileName="/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/DigitizationTests/mc15_pPb8TeV.361107.PowhegPythia8EvtGen_AZNLOCTEQ6L1_Zmumu.simul.HITS.e5367_s3164.HITS.11308894._000005.pool.root.1" +HeavyIonHITSFileName="/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/DigitizationTests/mc15_pPb8TeV.420112.Hijing_MinBiasDiff_pPb_8TeV.merge.HITS.e5328_s3148_s3153.HITS.11232927._000249.pool.root.1" + +Digi_tf.py \ +--inputHITSFile ${ZmumuHITSFileName} \ +--inputCavernHitsFile ${HeavyIonHITSFileName} \ +--outputRDOFile ${DigiOutFileName} \ +--maxEvents 10 \ +--skipEvents 0 \ +--numberOfCavernBkg 1 \ +--preExec 'all:rec.doHIP.set_Value_and_Lock(True);from AthenaCommon.BeamFlags import jobproperties;jobproperties.Beam.numberOfCollisions.set_Value_and_Lock(0.0);jobproperties.Beam.bunchSpacing.set_Value_and_Lock(25);from LArROD.LArRODFlags import larRODFlags;larRODFlags.nSamples.set_Value_and_Lock(4);from LArDigitization.LArDigitizationFlags import jobproperties;jobproperties.LArDigitizationFlags.useFcalHighGain.set_Value_and_Lock(True)' 'HITtoRDO:from Digitization.DigitizationFlags import digitizationFlags;digitizationFlags.overrideMetadata+=["PhysicsList"]' \ +--preInclude 'HITtoRDO:Digitization/ForceUseOfPileUpTools.py' \ +--postExec 'all:CfgMgr.MessageSvc().setError+=["HepMcParticleLink"]' 'HITtoRDO:from AthenaCommon import CfgGetter;mergeMcEventCollTool=CfgGetter.getPublicTool("MergeMcEventCollTool").DoSlimming=False' \ +--postInclude 'all:PyJobTransforms/UseFrontier.py,SimulationJobOptions/postInclude.HijingPars.py' \ +--geometryVersion ATLAS-R2-2015-03-01-00 \ +--conditionsTag all:OFLCOND-MC15c-SDR-15 \ +--DataRunNumber 295000 \ +--pileupInitialBunch 0 \ +--pileupFinalBunch 0 \ +--bunchSpacing 100 \ +--imf False + +echo "art-result: $? Digi_tf.py" diff --git a/Simulation/Tests/SimExoticsTests/CMakeLists.txt b/Simulation/Tests/SimExoticsTests/CMakeLists.txt index 7c7a8a939c6db5371acce476ab8b1f0d8f50e314..515b6508a8f4baa68eb284298b7f2ac0f282a269 100644 --- a/Simulation/Tests/SimExoticsTests/CMakeLists.txt +++ b/Simulation/Tests/SimExoticsTests/CMakeLists.txt @@ -10,5 +10,5 @@ atlas_depends_on_subdirs( PRIVATE TestPolicy ) # Install files from the package: -atlas_install_runtime( test/SimExoticsTests_TestConfiguration.xml ) +atlas_install_runtime( test/*.sh ) diff --git a/Simulation/Tests/SimExoticsTests/test/SimExoticsTests_TestConfiguration.xml b/Simulation/Tests/SimExoticsTests/test/SimExoticsTests_TestConfiguration.xml deleted file mode 100644 index 10e2e2f5bef28f4d30f1f100134c676654848dd8..0000000000000000000000000000000000000000 --- a/Simulation/Tests/SimExoticsTests/test/SimExoticsTests_TestConfiguration.xml +++ /dev/null @@ -1,293 +0,0 @@ -<!DOCTYPE unifiedTestConfiguration SYSTEM "http://www.hep.ucl.ac.uk/atlas/AtlasTesting/DTD/unifiedTestConfiguration.dtd"> -<unifiedTestConfiguration> - <rtt xmlns="http://www.hep.ucl.ac.uk/atlas/AtlasTesting/rtt"> - <rttContactPerson>Andreas Schaelicke (andreas.schaelicke@cern.ch)</rttContactPerson> - <mailto>atlas-simulation-testreports@cern.ch</mailto> - <refRelease>17.2.7</refRelease> - -<!-- - don't forget to check the xml file with - python /afs/cern.ch/user/r/rtt/public/validateXML.py SimExoticsTests_TestConfiguration.xml - and to update the twiki page: - https://twiki.cern.ch/twiki/bin/viewauth/Atlas/SimExoticsTests ---> - - <jobList> - - <classification> - <displayClass>OfflineValidation</displayClass> - <displayProcess>Simul</displayProcess> - <displayComponent>Athena-Core</displayComponent> - </classification> - <chain> - <chainName>StableRHadrons114865</chainName> - <sequential> - <chainElement> - <jobTransform userJobId="StableRHadronEvgen114865"> - <doc>PYTHIA6 R-Hadrons stable generic stop 600GeV</doc> - <jobTransformJobName>StableRHadronEvgen114865</jobTransformJobName> - <jobTransformCmd> -export DATAPATH=/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests:$DATAPATH; Generate_tf.py --ecmEnergy='8000' --runNumber='114865' --firstEvent='1' --maxEvents='6000' --randomSeed='50097493' --jobConfig='/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests/MC14.114865.PythiaRhad_AUET2B_CTEQ6L1_regge_stop_600GeV.py' --outputEVNTFile='evgen.pool.root' -</jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <queue>short</queue> - </jobTransform> - <chainfileout>evgen.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="StableRHadronSim114865"> - <doc>PYTHIA6 R-Hadrons stable generic stop 600GeV - Simulation</doc> - <jobTransformJobName>StableRHadronSim114865</jobTransformJobName> - <jobTransformCmd> -AtlasG4_tf.py --inputEVNTFile evgen.pool.root --outputHITSFile test.HITS.pool.root --conditionsTag 'OFLCOND-RUN12-SDR-19' --physicsList FTFP_BERT_ATL --maxEvents 10 --geometryVersion 'ATLAS-R2-2015-03-01-00' --DataRunNumber '222525' --randomSeed 9375655 - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <chaindataset_info> - <jobTransformData /> - <chaindatasetName>evgen.pool.root</chaindatasetName> - <dataset_info> - <jobTransformData /> - <datasetName>/eos/atlas/atlascerngroupdisk/proj-sit/simulation/validation/RTT/referenceFiles/18.X.0/StableRHadrons114865.EVNT.pool.root</datasetName> - </dataset_info> - </chaindataset_info> - <queue>long</queue> - <batchWallTime>300</batchWallTime> - </jobTransform> - <chainfileout>test.HITS.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="StableRHadronSim114865_Reg"> - <doc>Regression test between releases</doc> - <jobTransformJobName>StableRHadronSim114865_Reg</jobTransformJobName> - <jobTransformCmd>sim_reg_test.py StableRHadronSim114865 test.HITS.pool.root HITS.pool</jobTransformCmd> - <group>SimCoreTests:SimCoreRegressionTests</group> - <queue>short</queue> - </jobTransform> - </chainElement> - </sequential> - </chain> - <chain> - <chainName>StableRHadrons114875</chainName> - <sequential> - <chainElement> - <jobTransform userJobId="StableRHadronEvgen114875"> - <doc>PYTHIA6 R-Hadrons stable generic sbottom 600GeV</doc> - <jobTransformJobName>StableRHadronEvgen114875</jobTransformJobName> - <jobTransformCmd> -export DATAPATH=/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests:$DATAPATH; Generate_tf.py --ecmEnergy='8000' --runNumber='114875' --firstEvent='1' --maxEvents='6000' --randomSeed='50097493' --jobConfig='/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests/MC14.114875.PythiaRhad_AUET2B_CTEQ6L1_regge_sbottom_600GeV.py' --outputEVNTFile='evgen.pool.root' - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <queue>short</queue> - </jobTransform> - <chainfileout>evgen.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="StableRHadronSim114875"> - <doc>PYTHIA6 R-Hadrons stable generic sbottom 600GeV - Simulation</doc> - <jobTransformJobName>StableRHadronSim114875</jobTransformJobName> - <jobTransformCmd> -AtlasG4_tf.py --inputEVNTFile evgen.pool.root --outputHITSFile test.HITS.pool.root --conditionsTag 'OFLCOND-RUN12-SDR-19' --physicsList FTFP_BERT_ATL --maxEvents 10 --geometryVersion 'ATLAS-R2-2015-03-01-00' --DataRunNumber '222525' --randomSeed 9375655 - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <chaindataset_info> - <jobTransformData /> - <chaindatasetName>evgen.pool.root</chaindatasetName> - <dataset_info> - <jobTransformData /> - <datasetName>/eos/atlas/atlascerngroupdisk/proj-sit/simulation/validation/RTT/referenceFiles/18.X.0/StableRHadrons114875.EVNT.pool.root</datasetName> - </dataset_info> - </chaindataset_info> - <queue>long</queue> - <batchWallTime>300</batchWallTime> - </jobTransform> - <chainfileout>test.HITS.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="StableRHadronSim114875_Reg"> - <doc>Regression test between releases</doc> - <jobTransformJobName>StableRHadronSim114875_Reg</jobTransformJobName> - <jobTransformCmd>sim_reg_test.py StableRHadronSim114875 test.HITS.pool.root HITS.pool</jobTransformCmd> - <group>SimCoreTests:SimCoreRegressionTests</group> - <queue>short</queue> - </jobTransform> - </chainElement> - </sequential> - </chain> - <chain> - <chainName>StableRHadrons176089</chainName> - <sequential> - <chainElement> - <jobTransform userJobId="StableRHadronEvgen176089"> - <doc>PYTHIA6 R-Hadrons stable generic gluino gball0.1 1000GeV</doc> - <jobTransformJobName>StableRHadronEvgen176089</jobTransformJobName> - <jobTransformCmd> -export DATAPATH=/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests:$DATAPATH; Generate_tf.py --ecmEnergy='8000' --runNumber='176089' --firstEvent='1' --maxEvents='6000' --randomSeed='50097493' --jobConfig='/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests/MC14.176089.PythiaRhad_AUET2B_CTEQ6L1_gener_gluino_0p1_1000GeV.py' --outputEVNTFile='evgen.pool.root' - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <queue>short</queue> - </jobTransform> - <chainfileout>evgen.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="StableRHadronSim176089"> - <doc>PYTHIA6 R-Hadrons stable generic gluino gball0.1 1000GeV - Simulation</doc> - <jobTransformJobName>StableRHadronSim176089</jobTransformJobName> - <jobTransformCmd> -AtlasG4_tf.py --inputEVNTFile evgen.pool.root --outputHITSFile test.HITS.pool.root --conditionsTag 'OFLCOND-RUN12-SDR-19' --physicsList FTFP_BERT_ATL --maxEvents 10 --geometryVersion 'ATLAS-R2-2015-03-01-00' --DataRunNumber '222525' --randomSeed 9375655 - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <chaindataset_info> - <jobTransformData /> - <chaindatasetName>evgen.pool.root</chaindatasetName> - <dataset_info> - <jobTransformData /> - <datasetName>/eos/atlas/atlascerngroupdisk/proj-sit/simulation/validation/RTT/referenceFiles/18.X.0/StableRHadrons176089.EVNT.pool.root</datasetName> - </dataset_info> - </chaindataset_info> - <queue>long</queue> - <batchWallTime>300</batchWallTime> - </jobTransform> - <chainfileout>test.HITS.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="StableRHadronSim176089_Reg"> - <doc>Regression test between releases</doc> - <jobTransformJobName>StableRHadronSim176089_Reg</jobTransformJobName> - <jobTransformCmd>sim_reg_test.py StableRHadronSim176089 test.HITS.pool.root HITS.pool</jobTransformCmd> - <group>SimCoreTests:SimCoreRegressionTests</group> - <queue>short</queue> - </jobTransform> - </chainElement> - </sequential> - </chain> - - <chain> - <chainName>AMSB_500GeV_Chargino_1ns</chainName> - <sequential> - <chainElement> - <jobTransform userJobId="AMSB_500GeV_Chargino_1nsEvgen"> - <doc>Evgen AMSB 500GeV Charginos 1ns lifetime</doc> - <jobTransformJobName>AMSB_500GeV_Chargino_1nsEvgen</jobTransformJobName> - <jobTransformCmd> -export DATAPATH=/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests:$DATAPATH; Generate_tf.py --ecmEnergy=8000 --runNumber=174309 --firstEvent=1 --randomSeed=1 --jobConfig=/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests/MC14.174309.Herwigpp_UEEE3_CTEQ6L1_mAMSB_EW_1000_175000_5_P_LL1p0_1jet.py --outputEVNTFile=evgen.pool.root --maxEvents=500 - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <queue>short</queue> - </jobTransform> - <chainfileout>evgen.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="AMSB_500GeV_Chargino_1nsSim"> - <doc>Simulation AMSB 500GeV Charginos 1ns lifetime</doc> - <jobTransformJobName>AMSB_500GeV_Chargino_1nsSim</jobTransformJobName> - <jobTransformCmd> -AtlasG4_tf.py --inputEVNTFile evgen.pool.root --outputHITSFile test.HITS.pool.root --conditionsTag 'OFLCOND-RUN12-SDR-19' --physicsList FTFP_BERT_ATL --maxEvents 100 --geometryVersion 'ATLAS-R2-2015-03-01-00' --DataRunNumber '222525' --randomSeed 10 - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <chaindataset_info> - <jobTransformData /> - <chaindatasetName>evgen.pool.root</chaindatasetName> - <dataset_info> - <jobTransformData /> - <datasetName>/eos/atlas/atlascerngroupdisk/proj-sit/simulation/validation/RTT/referenceFiles/18.X.0/AMSB_500GeV_Chargino_1ns.EVNT.pool.root</datasetName> - </dataset_info> - </chaindataset_info> - <queue>long</queue> - <batchWallTime>300</batchWallTime> - </jobTransform> - <chainfileout>test.HITS.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="AMSB_500GeV_Chargino_1nsSim_Reg"> - <doc>Regression test between releases</doc> - <jobTransformJobName>AMSB_500GeV_Chargino_1nsSim_Reg</jobTransformJobName> - <jobTransformCmd>sim_reg_test.py AMSB_500GeV_Chargino_1nsSim test.HITS.pool.root HITS.pool</jobTransformCmd> - <group>SimCoreTests:SimCoreRegressionTests</group> - <queue>short</queue> - </jobTransform> - </chainElement> - </sequential> - </chain> - - <chain> - <chainName>Monopole</chainName> - <sequential> - <chainElement> - <jobTransform userJobId="Monopole_Evgen"> - <doc>Evgen Monopole</doc> - <jobTransformJobName>Monopole_Evgen</jobTransformJobName> - <jobTransformCmd> -export DATAPATH=/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests:$DATAPATH; Generate_tf.py --ecmEnergy='8000' --runNumber='188762' --firstEvent='1' --maxEvents='5000' --randomSeed='1' --jobConfig='/afs/cern.ch/atlas/groups/Generators/MC14JobOptions/latest/share/tests/MC14.188762.ParticleGenerator_SingleMonopole.py' --outputEVNTFile='evgen.pool.root' - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <queue>short</queue> - </jobTransform> - <chainfileout>evgen.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="Monopole_Sim"> - <doc>Simulation Monopole</doc> - <jobTransformJobName>Monopole_Sim</jobTransformJobName> - <jobTransformCmd> -AtlasG4_tf.py --inputEVNTFile evgen.pool.root --outputHITSFile test.HITS.pool.root --conditionsTag 'OFLCOND-RUN12-SDR-19' --physicsList FTFP_BERT_ATL --maxEvents 100 --geometryVersion 'ATLAS-R2-2015-03-01-00' --DataRunNumber '222525' --randomSeed 10 - </jobTransformCmd> - <group>ExoticGenJobTransforms</group> - <chaindataset_info> - <jobTransformData /> - <chaindatasetName>evgen.pool.root</chaindatasetName> - <dataset_info> - <jobTransformData /> - <datasetName>/eos/atlas/atlascerngroupdisk/proj-sit/simulation/validation/RTT/referenceFiles/18.X.0/Monopole.EVNT.pool.root</datasetName> - </dataset_info> - </chaindataset_info> - <queue>long</queue> - <batchWallTime>300</batchWallTime> - </jobTransform> - <chainfileout>test.HITS.pool.root</chainfileout> - </chainElement> - <chainElement> - <jobTransform userJobId="Monopole_Sim_Reg"> - <doc>Regression test between releases</doc> - <jobTransformJobName>Monopole_Sim_Reg</jobTransformJobName> - <jobTransformCmd>sim_reg_test.py Monopole_Sim test.HITS.pool.root HITS.pool</jobTransformCmd> - <group>SimCoreTests:SimCoreRegressionTests</group> - <queue>short</queue> - </jobTransform> - </chainElement> - </sequential> - </chain> - - <!-- NOTE:: make -omitvalidation to start with two "-" --> - </jobList> - - <jobGroups> - <!-- note: the job groups have also be known to Factory_ScriptWriter.py in order to work in RTT --> - <jobGroup name="ExoticJobTransform" parent="Top"> - <keepFilePattern>fileGrepper_results.txt</keepFilePattern> - <keepFilePattern>*.root</keepFilePattern> - <keepFilePattern>*.txt</keepFilePattern> - <keepFilePattern>log.*</keepFilePattern> - <keepFilePattern>*.log</keepFilePattern> - <keepFilePattern>*.diffPool</keepFilePattern> - </jobGroup> - - - <jobGroup name="ExoticGenJobTransforms" parent="ExoticJobTransform"> - <!-- nothing to configure (yet) --> - </jobGroup> - - <jobGroup name="ExoticSimJobTransforms" parent="ExoticJobTransform"> - <!-- nothing to configure (yet) --> - </jobGroup> - - - <jobGroup name="ExoticDigiJobTransforms" parent="ExoticJobTransform"> - <!-- nothing to configure (yet) --> - </jobGroup> - - </jobGroups> - - - </rtt> - -</unifiedTestConfiguration> diff --git a/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingCharginos.sh b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingCharginos.sh new file mode 100755 index 0000000000000000000000000000000000000000..a8e7c5ba15ec7ebf4e46784b846e3252794c3d92 --- /dev/null +++ b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingCharginos.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# art-description: MC16-style simulation of decaying Charginos using FullG4 (tests Charginos and Gauginos packages) +# art-type: grid +# art-include: 21.0/Athena +# art-include: 21.0/AthSimulation +# art-include: 21.3/Athena +# art-include: 21.9/Athena +# art-include: master/Athena +# art-include: master/AthSimulation + +# MC16 setup +# ATLAS-R2-2016-01-00-01 and OFLCOND-MC16-SDR-14 +Sim_tf.py \ +--conditionsTag 'default:OFLCOND-MC16-SDR-14' \ +--physicsList 'FTFP_BERT_ATL' \ +--truthStrategy 'MC15aPlusLLP' \ +--simulator 'FullG4' \ +--postInclude 'default:PyJobTransforms/UseFrontier.py' \ +--preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py' \ +--DataRunNumber '284500' \ +--geometryVersion 'default:ATLAS-R2-2016-01-00-01' \ +--inputEVNTFile "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/SimCoreTests/mc15_13TeV.448307.MGPy8EG_A14N23LO_mAMSB_C1C1_5000_208000_LL4p0_MET60.evgen.EVNT.e6962.EVNT.15631425._000001.pool.root.1" \ +--outputHITSFile "Hits.pool.root" \ +--maxEvents 10 \ +--imf False + +rc=$? +echo "art-result: $rc simulation" +rc2=-9999 +if [ $rc -eq 0 ] +then + ArtPackage=$1 + ArtJobName=$2 + art.py compare grid --entries 10 ${ArtPackage} ${ArtJobName} --mode=summary + rc2=$? +fi +echo "art-result: $rc2 regression" diff --git a/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingCharginos_busy.sh b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingCharginos_busy.sh new file mode 100755 index 0000000000000000000000000000000000000000..e9a64b838b588f21509608137e078c2052a0327d --- /dev/null +++ b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingCharginos_busy.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# art-description: MC16-style simulation of decaying Charginos (busy events) using FullG4 (tests Charginos and Gauginos packages) +# art-type: grid +# art-include: 21.0/Athena +# art-include: 21.0/AthSimulation +# art-include: 21.3/Athena +# art-include: 21.9/Athena +# art-include: master/Athena +# art-include: master/AthSimulation + +# MC16 setup +# ATLAS-R2-2016-01-00-01 and OFLCOND-MC16-SDR-14 +Sim_tf.py \ +--conditionsTag 'default:OFLCOND-MC16-SDR-14' \ +--physicsList 'FTFP_BERT_ATL' \ +--truthStrategy 'MC15aPlusLLP' \ +--simulator 'FullG4' \ +--postInclude 'default:PyJobTransforms/UseFrontier.py' \ +--preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py' \ +--DataRunNumber '284500' \ +--geometryVersion 'default:ATLAS-R2-2016-01-00-01' \ +--inputEVNTFile "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/SimCoreTests/mc15_13TeV.448300.MGPy8EG_A14N23LO_GG_mixedC1LLP_0p2_1400_1200.evgen.EVNT.e7183.EVNT.16706750._000001.pool.root.1" \ +--outputHITSFile "Hits.pool.root" \ +--maxEvents 4 \ +--imf False + +rc=$? +echo "art-result: $rc simulation" +rc2=-9999 +if [ $rc -eq 0 ] +then + ArtPackage=$1 + ArtJobName=$2 + art.py compare grid --entries 4 ${ArtPackage} ${ArtJobName} --mode=summary + rc2=$? +fi +echo "art-result: $rc2 regression" diff --git a/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingLightSleptons.sh b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingLightSleptons.sh new file mode 100755 index 0000000000000000000000000000000000000000..b4c25825aa061c30058899975efa2e2d4faa64f2 --- /dev/null +++ b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingLightSleptons.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# art-description: MC16-style simulation of decaying light sleptons using FullG4 (tests Sleptons + Gauginos) +# art-type: grid +# art-include: 21.0/Athena +# art-include: 21.0/AthSimulation +# art-include: 21.3/Athena +# art-include: 21.9/Athena +# art-include: master/Athena +# art-include: master/AthSimulation + +# MC16 setup +# ATLAS-R2-2016-01-00-01 and OFLCOND-MC16-SDR-14 +Sim_tf.py \ +--conditionsTag 'default:OFLCOND-MC16-SDR-14' \ +--physicsList 'FTFP_BERT_ATL' \ +--truthStrategy 'MC15aPlusLLP' \ +--simulator 'FullG4' \ +--postInclude 'default:PyJobTransforms/UseFrontier.py' \ +--preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py' \ +--DataRunNumber '284500' \ +--geometryVersion 'default:ATLAS-R2-2016-01-00-01' \ +--inputEVNTFile "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/SimCoreTests/mc15_13TeV.399030.MGPy8EG_A14NNPDF23LO_SlepSlep_directLLP_100_0_0p01ns.evgen.EVNT.e7067.EVNT.16242732._000001.pool.root.1" \ +--outputHITSFile "Hits.pool.root" \ +--maxEvents 10 \ +--imf False + +rc=$? +echo "art-result: $rc simulation" +rc2=-9999 +if [ $rc -eq 0 ] +then + ArtPackage=$1 + ArtJobName=$2 + art.py compare grid --entries 10 ${ArtPackage} ${ArtJobName} --mode=summary + rc2=$? +fi +echo "art-result: $rc2 regression" diff --git a/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingNeutralinos.sh b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingNeutralinos.sh new file mode 100755 index 0000000000000000000000000000000000000000..8b60764fc8b52534ef7677965ea2994bd883702c --- /dev/null +++ b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingNeutralinos.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# art-description: MC16-style simulation of decaying Neutralinos using FullG4 (tests sim response to many displaced “primary†particles) +# art-type: grid +# art-include: 21.0/Athena +# art-include: 21.0/AthSimulation +# art-include: 21.3/Athena +# art-include: 21.9/Athena +# art-include: master/Athena +# art-include: master/AthSimulation + +# MC16 setup +# ATLAS-R2-2016-01-00-01 and OFLCOND-MC16-SDR-14 +Sim_tf.py \ +--conditionsTag 'default:OFLCOND-MC16-SDR-14' \ +--physicsList 'FTFP_BERT_ATL' \ +--truthStrategy 'MC15aPlusLLP' \ +--simulator 'FullG4' \ +--postInclude 'default:PyJobTransforms/UseFrontier.py' \ +--preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py' \ +--DataRunNumber '284500' \ +--geometryVersion 'default:ATLAS-R2-2016-01-00-01' \ +--inputEVNTFile "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/SimCoreTests/mc15_13TeV.448168.MGPy8EG_A14NNPDF23LO_GG_qqn1_2400_850_rpvLF_p01ns.evgen.EVNT.e7245.EVNT.17092338._000002.pool.root.1" \ +--outputHITSFile "Hits.pool.root" \ +--maxEvents 10 \ +--imf False + +rc=$? +echo "art-result: $rc simulation" +rc2=-9999 +if [ $rc -eq 0 ] +then + ArtPackage=$1 + ArtJobName=$2 + art.py compare grid --entries 10 ${ArtPackage} ${ArtJobName} --mode=summary + rc2=$? +fi +echo "art-result: $rc2 regression" diff --git a/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingStaus.sh b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingStaus.sh new file mode 100755 index 0000000000000000000000000000000000000000..18d2d005ba5154c8cce5a8d3f6d1aa5b0a09b3bb --- /dev/null +++ b/Simulation/Tests/SimExoticsTests/test/test_FullG4_DecayingStaus.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# art-description: MC16-style simulation of decaying staus using FullG4 (tests the Sleptons + Gauginos packages) +# art-type: grid +# art-include: 21.0/Athena +# art-include: 21.0/AthSimulation +# art-include: 21.3/Athena +# art-include: 21.9/Athena +# art-include: master/Athena +# art-include: master/AthSimulation + +# MC16 setup +# ATLAS-R2-2016-01-00-01 and OFLCOND-MC16-SDR-14 +Sim_tf.py \ +--conditionsTag 'default:OFLCOND-MC16-SDR-14' \ +--physicsList 'FTFP_BERT_ATL' \ +--truthStrategy 'MC15aPlusLLP' \ +--simulator 'FullG4' \ +--postInclude 'default:PyJobTransforms/UseFrontier.py' \ +--preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py' \ +--DataRunNumber '284500' \ +--geometryVersion 'default:ATLAS-R2-2016-01-00-01' \ +--inputEVNTFile "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/SimCoreTests/mc15_13TeV.399007.MGPy8EG_A14NNPDF23LO_StauStau_directLLP_100_0_1ns.evgen.EVNT.e7067.EVNT.16137672._000001.pool.root.1" \ +--outputHITSFile "Hits.pool.root" \ +--maxEvents 10 \ +--imf False + +rc=$? +echo "art-result: $rc simulation" +rc2=-9999 +if [ $rc -eq 0 ] +then + ArtPackage=$1 + ArtJobName=$2 + art.py compare grid --entries 10 ${ArtPackage} ${ArtJobName} --mode=summary + rc2=$? +fi +echo "art-result: $rc2 regression" diff --git a/Simulation/Tests/SimExoticsTests/test/test_FullG4_StableCharginos.sh b/Simulation/Tests/SimExoticsTests/test/test_FullG4_StableCharginos.sh new file mode 100755 index 0000000000000000000000000000000000000000..b9e3e953f75235fc0ddb69ce3fc4fc346c1c0175 --- /dev/null +++ b/Simulation/Tests/SimExoticsTests/test/test_FullG4_StableCharginos.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# art-description: MC16-style simulation of stable Charginos using FullG4 (tests the Charginos package alone) +# art-type: grid +# art-include: 21.0/Athena +# art-include: 21.0/AthSimulation +# art-include: 21.3/Athena +# art-include: 21.9/Athena +# art-include: master/Athena +# art-include: master/AthSimulation + +# MC16 setup +# ATLAS-R2-2016-01-00-01 and OFLCOND-MC16-SDR-14 +Sim_tf.py \ +--conditionsTag 'default:OFLCOND-MC16-SDR-14' \ +--physicsList 'FTFP_BERT_ATL' \ +--truthStrategy 'MC15aPlusLLP' \ +--simulator 'FullG4' \ +--postInclude 'default:PyJobTransforms/UseFrontier.py' \ +--preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py' \ +--DataRunNumber '284500' \ +--geometryVersion 'default:ATLAS-R2-2016-01-00-01' \ +--inputEVNTFile "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/SimCoreTests/mc15_13TeV.404460.MGPy8EG_A14N23LO_mAMSB_C1C1_5000_68000_Stable.evgen.EVNT.e5654.EVNT.13360885._000001.pool.root.1" \ +--outputHITSFile "Hits.pool.root" \ +--maxEvents 10 \ +--imf False + +rc=$? +echo "art-result: $rc simulation" +rc2=-9999 +if [ $rc -eq 0 ] +then + ArtPackage=$1 + ArtJobName=$2 + art.py compare grid --entries 10 ${ArtPackage} ${ArtJobName} --mode=summary + rc2=$? +fi +echo "art-result: $rc2 regression" diff --git a/Simulation/Tests/SimExoticsTests/test/test_FullG4_StableSleptons.sh b/Simulation/Tests/SimExoticsTests/test/test_FullG4_StableSleptons.sh new file mode 100755 index 0000000000000000000000000000000000000000..225b0e886af0db5c51ba2645463aea14ba0d9991 --- /dev/null +++ b/Simulation/Tests/SimExoticsTests/test/test_FullG4_StableSleptons.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# +# art-description: MC16-style simulation of stable Sleptons using FullG4 (tests Sleptons package alone) +# art-type: grid +# art-include: 21.0/Athena +# art-include: 21.0/AthSimulation +# art-include: 21.3/Athena +# art-include: 21.9/Athena +# art-include: master/Athena +# art-include: master/AthSimulation + +# MC16 setup +# ATLAS-R2-2016-01-00-01 and OFLCOND-MC16-SDR-14 +Sim_tf.py \ +--conditionsTag 'default:OFLCOND-MC16-SDR-14' \ +--physicsList 'FTFP_BERT_ATL' \ +--truthStrategy 'MC15aPlusLLP' \ +--simulator 'FullG4' \ +--postInclude 'default:PyJobTransforms/UseFrontier.py' \ +--preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py,SimulationJobOptions/preInclude.FrozenShowersFCalOnly.py' \ +--DataRunNumber '284500' \ +--geometryVersion 'default:ATLAS-R2-2016-01-00-01' \ +--inputEVNTFile "/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/SimCoreTests/mc15_13TeV.404510.MGPy8EG_A14N23LO_GMSB_stablestau_lambda_090_tanb_10_dy.evgen.EVNT.e5652.EVNT.13360872._000001.pool.root.1" \ +--outputHITSFile "Hits.pool.root" \ +--maxEvents 10 \ +--imf False + +rc=$? +echo "art-result: $rc simulation" +rc2=-9999 +if [ $rc -eq 0 ] +then + ArtPackage=$1 + ArtJobName=$2 + art.py compare grid --entries 10 ${ArtPackage} ${ArtJobName} --mode=summary + rc2=$? +fi +echo "art-result: $rc2 regression" diff --git a/TileCalorimeter/TileExample/TileRecEx/share/jobOptions_TileCalibRec.py b/TileCalorimeter/TileExample/TileRecEx/share/jobOptions_TileCalibRec.py index 5956005ed0fd0a54e04b6545598f04bfc014703a..8e80d3480a5ad5b7d5f05451b58829671567930d 100644 --- a/TileCalorimeter/TileExample/TileRecEx/share/jobOptions_TileCalibRec.py +++ b/TileCalorimeter/TileExample/TileRecEx/share/jobOptions_TileCalibRec.py @@ -466,6 +466,9 @@ if not 'doTileMF' in dir(): if not 'doTileOF1' in dir(): doTileOF1 = False +if not 'doTileWiener' in dir(): + doTileWiener = False + if not 'doTileFit' in dir(): doTileFit = not TileCompareMode and ReadDigits @@ -511,7 +514,7 @@ if not 'OfcFromCOOL' in dir(): else: OfcFromCOOL = False -if useRODReco or doTileOpt2 or doTileMF or doTileOF1 or doTileOptATLAS or doTileFitCool or TileCompareMode or not 'TileUseCOOL' in dir(): +if useRODReco or doTileOpt2 or doTileMF or doTileOF1 or doTileOptATLAS or doTileWiener or doTileFitCool or TileCompareMode or not 'TileUseCOOL' in dir(): TileUseCOOL = True TileUseCOOLOFC = not ReadPool or OfcFromCOOL @@ -843,6 +846,12 @@ else: from xAODEventInfoCnv.xAODEventInfoCreator import xAODMaker__EventInfoCnvAlg topSequence+=xAODMaker__EventInfoCnvAlg() +#============================================================ +#=== configure BunchCrossingTool +#============================================================ +from TrigBunchCrossingTool.BunchCrossingTool import BunchCrossingTool +ToolSvc += BunchCrossingTool("LHC" if globalflags.DataSource() == "data" else "MC") + #============================================================= #=== read ByteStream and reconstruct data #============================================================= @@ -941,6 +950,19 @@ if doTileOF1: print ToolSvc.TileRawChannelBuilderOF1 +if doTileWiener: + if PhaseFromCOOL: + ToolSvc.TileRawChannelBuilderWienerFilter.TileCondToolTiming = tileInfoConfigurator.TileCondToolTiming + ToolSvc.TileRawChannelBuilderWienerFilter.correctTime = False # do not need to correct time with best phase + + ToolSvc.TileRawChannelBuilderWienerFilter.BestPhase = PhaseFromCOOL # Phase from COOL or assume phase=0 + if TileCompareMode or TileEmulateDSP: + ToolSvc.TileRawChannelBuilderWienerFilter.EmulateDSP = True # use dsp emulation + ToolSvc.TileRawChannelBuilderWienerFilter.UseDSPCorrection = not TileBiGainRun + ToolSvc.TileRawChannelBuilderWienerFilter.MC = globalflags.DataSource() != "data" + + print ToolSvc.TileRawChannelBuilderWienerFilter + if (doEventDisplay or doCreatePool): # create TileHit from TileRawChannel and store it in TileHitVec from TileRecAlgs.TileHitFromRawChGetter import * @@ -1278,6 +1300,9 @@ if doTileMon: if doTileMF: theTileRawChannelMon.TileRawChannelContainer = "TileRawChannelMF" + + if doTileWiener: + theTileRawChannelMon.TileRawChannelContainer = "TileRawChannelWiener" if useRODReco: theTileRawChannelMon.TileRawChannelContainerDSP = "TileRawChannelCnt" diff --git a/TileCalorimeter/TileIdentifier/TileIdentifier/TileFragHash.h b/TileCalorimeter/TileIdentifier/TileIdentifier/TileFragHash.h index f94912245c66bb2bd3e837144950f6498f81a8f5..7c642fba8f3be2dda3f8348b0a645791197b0016 100755 --- a/TileCalorimeter/TileIdentifier/TileIdentifier/TileFragHash.h +++ b/TileCalorimeter/TileIdentifier/TileIdentifier/TileFragHash.h @@ -31,7 +31,8 @@ class TileFragHash { /** initialize */ enum TYPE {Beam=255, Default=0, Digitizer=0, OptFilterDsp=1, OptFilterOffline=2, OptFilterDspCompressed=3, - ManyAmps=4, MF=5, FitFilter=6, FitFilterCool=7, FlatFilter=8 }; + ManyAmps=4, MF=5, FitFilter=6, FitFilterCool=7, FlatFilter=8, + WienerFilterOffline=9 }; void initialize(const TileHWID * tileHWID, TYPE type=Default ); diff --git a/TileCalorimeter/TileRec/TileRec/TileAANtuple.h b/TileCalorimeter/TileRec/TileRec/TileAANtuple.h index 76c8fd91444ecaf583db939acea31bffc980822b..b082bd8a77440bd2aefa09405b2a21a3ccd24591 100755 --- a/TileCalorimeter/TileRec/TileRec/TileAANtuple.h +++ b/TileCalorimeter/TileRec/TileRec/TileAANtuple.h @@ -22,6 +22,7 @@ /// TileRawChannelContainerFit key of fit filtered RawChannels in TDS /// TileRawChannelContainerFitCool key of fit filtered RawChannels in TDS /// TileRawChannelOF1 key of OF1 filtered RawChannels in TDS +/// TileRawChannelWiener key of Wiener filtered RawChannels in TDS /// TileLaserObject string key of Laser Object in TDS /// CalibrateEnergy bool If calibration should be applied to energy /// CalibMode bool If data is in calibration mode (bi-gain input) @@ -297,6 +298,11 @@ class TileAANtuple : public AthAlgorithm { float m_chi2MF[N_ROS2][N_MODULES][N_CHANS]; float m_pedMF[N_ROS2][N_MODULES][N_CHANS]; + float m_eWiener[N_ROS2][N_MODULES][N_CHANS]; + float m_tWiener[N_ROS2][N_MODULES][N_CHANS]; + float m_pedWiener[N_ROS2][N_MODULES][N_CHANS]; + float m_chi2Wiener[N_ROS2][N_MODULES][N_CHANS]; + short m_ROD_GlobalCRC[N_ROS][N_MODULES]; short m_ROD_BCID[N_ROS][N_MODULES]; short m_ROD_DMUBCIDErr[N_ROS][N_MODULES][N_DMUS]; @@ -340,6 +346,7 @@ class TileAANtuple : public AthAlgorithm { std::string m_dspRawChannelContainer; std::string m_mfRawChannelContainer; std::string m_of1RawChannelContainer; + std::string m_wienerRawChannelContainer; std::string m_laserObject; std::string m_tileMuRcvRawChannelContainer; // TMDB std::string m_tileMuRcvDigitsContainer; // TMDB diff --git a/TileCalorimeter/TileRec/share/TileDefaults_jobOptions.py b/TileCalorimeter/TileRec/share/TileDefaults_jobOptions.py index 84f446c1b7cc5dbd3125b450d9dfee274d4998c6..5bec251868ec7e0c9c9f339f1cf88680891441c2 100755 --- a/TileCalorimeter/TileRec/share/TileDefaults_jobOptions.py +++ b/TileCalorimeter/TileRec/share/TileDefaults_jobOptions.py @@ -11,6 +11,7 @@ if ('doSim' in dir()) and doSim: doTileQIE = False doTileOptATLAS = False doTileMF = False + doTileWiener = False doTileFit = False doTileFitCool = False TileCisRun = False @@ -61,6 +62,11 @@ if not 'doTileMF' in dir(): else: jobproperties.TileRecFlags.doTileMF = doTileMF +if not 'doTileWiener' in dir(): + doTileWiener = jobproperties.TileRecFlags.doTileWiener() +else: + jobproperties.TileRecFlags.doTileWiener = doTileWiener + if not 'doTileFit' in dir(): doTileFit = jobproperties.TileRecFlags.doTileFit() else: diff --git a/TileCalorimeter/TileRec/share/TileNtuple_jobOptions.py b/TileCalorimeter/TileRec/share/TileNtuple_jobOptions.py index ebca0914cdd328c666d5fec366cc812d5295e1ed..46861e8bd2ca891023fa8a9a99209aae74d1b69e 100755 --- a/TileCalorimeter/TileRec/share/TileNtuple_jobOptions.py +++ b/TileCalorimeter/TileRec/share/TileNtuple_jobOptions.py @@ -18,6 +18,7 @@ TileNtuple.TileRawChannelContainerOpt = "" TileNtuple.TileRawChannelContainerQIE = "" TileNtuple.TileRawChannelContainerOF1 = "" TileNtuple.TileRawChannelContainerMF = "" +TileNtuple.TileRawChannelContainerWiener = "" TileNtuple.TileRawChannelContainerDsp = "" TileNtuple.TileLaserObject = "" TileNtuple.TileMuRcvRawChannelContainer= "" @@ -87,6 +88,9 @@ else: if doTileMF: TileNtuple.TileRawChannelContainerMF = "TileRawChannelMF" + if doTileWiener: + TileNtuple.TileRawChannelContainerWiener = "TileRawChannelWiener" + if useTMDB: TileNtuple.TileMuRcvRawChannelContainer = "MuRcvRawChCnt" TileNtuple.TileMuRcvDigitsContainer = "MuRcvDigitsCnt" diff --git a/TileCalorimeter/TileRec/src/TileAANtuple.cxx b/TileCalorimeter/TileRec/src/TileAANtuple.cxx index 694beb6417868e98d4474ba37d7fc6d88bf319a8..36e339bcf7ffd6ca734d59a99541e964d82f4a0b 100755 --- a/TileCalorimeter/TileRec/src/TileAANtuple.cxx +++ b/TileCalorimeter/TileRec/src/TileAANtuple.cxx @@ -153,6 +153,10 @@ TileAANtuple::TileAANtuple(std::string name, ISvcLocator* pSvcLocator) , m_tMF() , m_chi2MF() , m_pedMF() +, m_eWiener() +, m_tWiener() +, m_pedWiener() +, m_chi2Wiener() , m_ROD_GlobalCRC() , m_ROD_BCID() , m_ROD_DMUBCIDErr() @@ -220,6 +224,7 @@ TileAANtuple::TileAANtuple(std::string name, ISvcLocator* pSvcLocator) declareProperty("TileRawChannelContainerOF1", m_of1RawChannelContainer = ""); // declareProperty("TileRawChannelContainerDsp", m_dspRawChannelContainer = ""); // declareProperty("TileRawChannelContainerMF", m_mfRawChannelContainer = ""); // + declareProperty("TileRawChannelContainerWiener", m_wienerRawChannelContainer = ""); // declareProperty("TileMuRcvRawChannelContainer", m_tileMuRcvRawChannelContainer = "MuRcvRawChCnt");// TMDB declareProperty("TileMuRcvDigitsContainer", m_tileMuRcvDigitsContainer = "MuRcvDigitsCnt");// TMDB declareProperty("TileMuRcvContainer", m_tileMuRcvContainer = "TileMuRcvCnt");// TMDB @@ -448,14 +453,15 @@ StatusCode TileAANtuple::execute() { // store TileRawChannels // start from DSP channels - so we can find out what is the DSP units - empty &= storeRawChannels(m_dspRawChannelContainer, m_eDsp, m_tDsp, m_chi2Dsp, m_pedDsp, true ).isFailure(); - empty &= storeRawChannels(m_rawChannelContainer, m_ene, m_time, m_chi2, m_ped, false).isFailure(); - empty &= storeMFRawChannels(m_mfRawChannelContainer, m_eMF, m_tMF, m_chi2MF, m_pedMF, false).isFailure(); - empty &= storeRawChannels(m_fitRawChannelContainer, m_eFit, m_tFit, m_chi2Fit, m_pedFit, false).isFailure(); - empty &= storeRawChannels(m_fitcRawChannelContainer, m_eFitc, m_tFitc, m_chi2Fitc,m_pedFitc,false).isFailure(); - empty &= storeRawChannels(m_optRawChannelContainer, m_eOpt, m_tOpt, m_chi2Opt, m_pedOpt, false).isFailure(); - empty &= storeRawChannels(m_qieRawChannelContainer, m_eQIE, m_tQIE, m_chi2QIE, m_pedQIE, false).isFailure(); - empty &= storeRawChannels(m_of1RawChannelContainer, m_eOF1, m_tOF1, m_chi2OF1, m_pedOF1, false).isFailure(); + empty &= storeRawChannels(m_dspRawChannelContainer, m_eDsp, m_tDsp, m_chi2Dsp, m_pedDsp, true ).isFailure(); + empty &= storeRawChannels(m_rawChannelContainer, m_ene, m_time, m_chi2, m_ped, false).isFailure(); + empty &= storeMFRawChannels(m_mfRawChannelContainer, m_eMF, m_tMF, m_chi2MF, m_pedMF, false).isFailure(); + empty &= storeRawChannels(m_fitRawChannelContainer, m_eFit, m_tFit, m_chi2Fit, m_pedFit, false).isFailure(); + empty &= storeRawChannels(m_fitcRawChannelContainer, m_eFitc, m_tFitc, m_chi2Fitc, m_pedFitc, false).isFailure(); + empty &= storeRawChannels(m_optRawChannelContainer, m_eOpt, m_tOpt, m_chi2Opt, m_pedOpt, false).isFailure(); + empty &= storeRawChannels(m_qieRawChannelContainer, m_eQIE, m_tQIE, m_chi2QIE, m_pedQIE, false).isFailure(); + empty &= storeRawChannels(m_of1RawChannelContainer, m_eOF1, m_tOF1, m_chi2OF1, m_pedOF1, false).isFailure(); + empty &= storeRawChannels(m_wienerRawChannelContainer, m_eWiener, m_tWiener, m_chi2Wiener, m_pedWiener, false).isFailure(); // store TMDB data // @@ -2061,6 +2067,13 @@ void TileAANtuple::DIGI_addBranch(void) m_ntuplePtr->Branch(NAME2("chi2MF",f_suf), m_chi2MF[ir], NAME3("chi2MF",f_suf,"[4][64][48]/F")); // float m_ntuplePtr->Branch(NAME2("pedMF",f_suf), m_pedMF[ir], NAME3("pedMF",f_suf,"[4][64][48]/F")); // float } + + if (m_wienerRawChannelContainer.size() > 0) { + m_ntuplePtr->Branch(NAME2("eWiener",f_suf), m_eWiener[ir], NAME3("eWiener",f_suf,"[4][64][48]/F")); // float + m_ntuplePtr->Branch(NAME2("tWiener",f_suf), m_tWiener[ir], NAME3("tWiener",f_suf,"[4][64][48]/F")); // float + m_ntuplePtr->Branch(NAME2("pedWiener",f_suf), m_pedWiener[ir], NAME3("pedWiener",f_suf,"[4][64][48]/F")); // float + m_ntuplePtr->Branch(NAME2("chi2Wiener",f_suf), m_chi2Wiener[ir], NAME3("chi2Wiener",f_suf,"[4][64][48]/F")); // float + } if (m_bsInput) { if (i == imin) { // common for low and high gain @@ -2190,6 +2203,13 @@ void TileAANtuple::DIGI_clearBranch(void) { CLEAR2(m_chi2MF, size); CLEAR2(m_pedMF, size); } + + if (m_wienerRawChannelContainer.size() > 0) { + CLEAR2(m_eWiener, size); + CLEAR2(m_tWiener, size); + CLEAR2(m_pedWiener, size); + CLEAR2(m_chi2Wiener, size); + } if (m_bsInput) { CLEAR1(m_ROD_GlobalCRC); diff --git a/TileCalorimeter/TileRecUtils/CMakeLists.txt b/TileCalorimeter/TileRecUtils/CMakeLists.txt index 35b8885701ce5f90f96fd5bd3500abec76f49911..19bd47164c8b64bb4cd9f14fc2d170327ccd376c 100644 --- a/TileCalorimeter/TileRecUtils/CMakeLists.txt +++ b/TileCalorimeter/TileRecUtils/CMakeLists.txt @@ -28,7 +28,8 @@ atlas_depends_on_subdirs( PUBLIC Event/xAOD/xAODEventInfo TileCalorimeter/TileCalib/TileCalibBlobObjs TileCalorimeter/TileDetDescr - Tools/PathResolver ) + Tools/PathResolver + Trigger/TrigAnalysis/TrigAnalysisInterfaces ) # External dependencies: find_package( Boost COMPONENTS filesystem thread system ) diff --git a/TileCalorimeter/TileRecUtils/TileRecUtils/TileRawChannelBuilderWienerFilter.h b/TileCalorimeter/TileRecUtils/TileRecUtils/TileRawChannelBuilderWienerFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..137ca4819d571b3469007f9e19de2d1127efcd16 --- /dev/null +++ b/TileCalorimeter/TileRecUtils/TileRecUtils/TileRawChannelBuilderWienerFilter.h @@ -0,0 +1,112 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TILERECUTILS_TILERAWCHANNELBUILDERWIENERFILTER_H +#define TILERECUTILS_TILERAWCHANNELBUILDERWIENERFILTER_H + +////////////////////////////////////////////////////////////////////// +// +// AUTHOR : G. Goncalves <ginaciog@cern.ch> +// CREATED: May 2019 +// +// TileRawChannelBuilderWienerFilter.h +// +// implementation of the Wiener Filter for +// energy/time reconstruction in TileCal +// +////////////////////////////////////////////////////////////////////// + +// Tile includes +#include "TileRecUtils/TileRawChannelBuilder.h" +#include "TileConditions/ITileCondToolOfc.h" +#include "TileConditions/TileCondToolTiming.h" +#include "TileConditions/TileCondToolNoiseSample.h" +#include "TrigAnalysisInterfaces/IBunchCrossingTool.h" + +#include <vector> +#include <string> + +/** + * + * @class TileRawChannelBuilderWienerFilter + * @brief Reconstructs Tile digitized pulses (ie, computes amplitude, time and pedestal) as a linear combination of the samples + * + * This class implements an energy reconstruction method known as Wiener + * Filter. It takes as input the digital samples from the digitizer boards + * in the front-end electronics and outputs the amplitude, time and pedestal + * of the pulse. Full details and fundaments of the method can be found in + * the ATL-TILECAL-PROC-2019-002 note. Two different versions of the algorithms + * are currently used: Wiener Optimal (with uses seven sets of weights, optimized + * for the first three, the middle and the last three BCIDs in the train) and + * Wiener General (one set of weights for all BCIDs). + */ +class TileRawChannelBuilderWienerFilter: public TileRawChannelBuilder { + public: + + TileRawChannelBuilderWienerFilter(const std::string& type, const std::string& name, + const IInterface *parent); //!< Constructor + ~TileRawChannelBuilderWienerFilter(); //!< Destructor + + // virtual methods + virtual StatusCode initialize(); //!< Initialize method + //virtual StatusCode execute(); + virtual StatusCode finalize(); //!< Finalize method + + // Inherited from TileRawChannelBuilder + virtual TileRawChannel* rawChannel(const TileDigits* digits); + + /** + * AlgTool InterfaceID + */ + static const InterfaceID& interfaceID(); + + private: + + //!< Callback added to handle Data-driven GeoModel initialization + virtual StatusCode geoInit(IOVSVC_CALLBACK_ARGS); + + ToolHandle<TileCondToolTiming> m_tileToolTiming; + ToolHandle<ITileCondToolOfc> m_tileCondToolOfc; + ToolHandle<TileCondToolNoiseSample> m_tileToolNoiseSample; //!< tool which provides noise values + ToolHandle<Trig::IBunchCrossingTool> m_bunchCrossingTool; + + //!< Applies OF algorithm + double filter(int ros, int drawer, int channel, int &gain, double &pedestal, double &litude, double &time); + int findMaxDigitPosition(); //!< Finds maximum digit position in the pulse + //!< Gets pedestal estimation for OF1 + float getPedestal(int ros, int drawer, int channel, int gain); + //!< Computes A,time,ped using OF. If iterations are required, the Iterator method is used + double compute(int ros, int drawer, int channel, int gain, double &pedestal, double &litude, double &time, double& phase); + //!< Gets the BCID index within the train + int getBCIDIndex(); + + int m_maxIterations; //!< maximum number of iteration to perform + int m_pedestalMode; //!< pedestal mode to use + bool m_confTB; //!< use testbeam configuration + double m_timeForConvergence; //!< minimum time difference to quit iteration procedure + bool m_isMC; //!< bool variable for MC: true=> MC; false=> data + bool m_minus1Iter; //!< bool variable for whether to apply -1 iteration (initial phase guess) + bool m_correctAmplitude; //!< If true, resulting amplitude is corrected when using weights for tau=0 without iteration + bool m_correctTimeNI; //!< If true, resulting time is corrected when using method without iteration + + bool m_bestPhase; // if true, use best phase from COOL DB in "fixed phase" mode (i.e., no iterations) + bool m_emulateDsp; // if true, emulate DSP reconstruction algorithm + int m_nSignal; //!< internal counters + int m_nNegative; //!< internal counters + int m_nCenter; //!< internal counters + int m_nConst; //!< internal counters + + int m_nSamples; //!< number of samples in the data + int m_t0SamplePosition; //!< position of peak sample = (m_nSamples-1)/2 + double m_maxTime; //!< max allowed time = 25*(m_nSamples-1)/2 + double m_minTime; //!< min allowed time = -25*(m_nSamples-1)/2 + + + std::vector<float> m_digits; + + static const float m_gfcWiener[8]; //!< Wiener General weights + static const float m_ofcWiener[7][8]; //!< Wiener Optimal weights +}; + +#endif diff --git a/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter.py b/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter.py index 8480a5932087d5c86a97578add132052d201cc79..c43300f2df6e44f3212c8fd3e1614a4b69fe8933 100644 --- a/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter.py +++ b/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter.py @@ -143,6 +143,7 @@ class TileRawChannelGetter ( Configured) : if (jobproperties.TileRecFlags.doTileMF() or (not jobproperties.TileRecFlags.OfcFromCOOL() and (jobproperties.TileRecFlags.doTileOF1() + or jobproperties.TileRecFlags.doTileWiener() or jobproperties.TileRecFlags.doTileOpt2() or jobproperties.TileRecFlags.doTileOptATLAS()))): @@ -154,6 +155,7 @@ class TileRawChannelGetter ( Configured) : if jobproperties.TileRecFlags.OfcFromCOOL(): if (jobproperties.TileRecFlags.doTileMF() + or jobproperties.TileRecFlags.doTileWiener() or jobproperties.TileRecFlags.doTileOpt2() or jobproperties.TileRecFlags.doTileOptATLAS()): @@ -488,6 +490,39 @@ class TileRawChannelGetter ( Configured) : ToolSvc += theTileRawChannelBuilderOptATLAS theTileRawChannelMaker.TileRawChannelBuilder += [ToolSvc.TileRawChannelBuilderOptATLAS] + + if jobproperties.TileRecFlags.doTileWiener(): + try: + from TileRecUtils.TileRecUtilsConf import TileRawChannelBuilderWienerFilter + theTileRawChannelBuilderWienerFilter= TileRawChannelBuilderWienerFilter() + except: + mlog.error("could not get handle to TileRawChannelBuilderWienerFilter Quit") + print traceback.format_exc() + return False + + # setup COOL to get OFCs + if jobproperties.TileRecFlags.OfcFromCOOL(): + theTileRawChannelBuilderWienerFilter.TileCondToolOfc = ToolSvc.TileCondToolOfcCool + + #TileRawChannelBuilderWienerFilter Options: + jobproperties.TileRecFlags.TileRawChannelContainer = "TileRawChannelWiener" + theTileRawChannelBuilderWienerFilter.TileRawChannelContainer = "TileRawChannelWiener" + theTileRawChannelBuilderWienerFilter.RunType = jobproperties.TileRecFlags.TileRunType() + theTileRawChannelBuilderWienerFilter.calibrateEnergy = jobproperties.TileRecFlags.calibrateEnergy() + theTileRawChannelBuilderWienerFilter.correctTime = jobproperties.TileRecFlags.correctTime() + theTileRawChannelBuilderWienerFilter.NoiseFilterTools = NoiseFilterTools + theTileRawChannelBuilderWienerFilter.BestPhase = False; # no point to use best phase with interations + theTileRawChannelBuilderWienerFilter.MC = False # use globalflags.DataSource()!='data' + theTileRawChannelBuilderWienerFilter.PedestalMode = 1 + theTileRawChannelBuilderWienerFilter.MaxIterations = 5 + theTileRawChannelBuilderWienerFilter.Minus1Iteration = True + theTileRawChannelBuilderWienerFilter.AmplitudeCorrection = False; # don't need correction after iterations + theTileRawChannelBuilderWienerFilter.TimeCorrection = False; # don't need correction after iterations + + mlog.info(" adding now TileRawChannelBuilderWienerFilter to ToolSvc") + ToolSvc += theTileRawChannelBuilderWienerFilter + + theTileRawChannelMaker.TileRawChannelBuilder += [ToolSvc.TileRawChannelBuilderWienerFilter] # now add algorithm to topSequence @@ -527,6 +562,7 @@ class TileRawChannelGetter ( Configured) : jobproperties.TileRecFlags.doTileManyAmps = False jobproperties.TileRecFlags.doTileMF = False jobproperties.TileRecFlags.doTileOF1 = False + jobproperties.TileRecFlags.doTileWiener = False jobproperties.TileRecFlags.OfcFromCOOL = False jobproperties.TileRecFlags.print_JobProperties('tree&value') diff --git a/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter_DigiHSTruth.py b/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter_DigiHSTruth.py index 642c2c572083ef6c85af958c95173a6989305cdd..1e4e960a1ae929824d68f29ab93b66b920197774 100644 --- a/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter_DigiHSTruth.py +++ b/TileCalorimeter/TileRecUtils/python/TileRawChannelGetter_DigiHSTruth.py @@ -177,6 +177,7 @@ class TileRawChannelGetter_DigiHSTruth ( Configured) : jobproperties.TileRecFlags.doTileManyAmps = False jobproperties.TileRecFlags.doTileMF = False jobproperties.TileRecFlags.doTileOF1 = False + jobproperties.TileRecFlags.doTileWiener = False jobproperties.TileRecFlags.OfcFromCOOL = False jobproperties.TileRecFlags.print_JobProperties('tree&value') diff --git a/TileCalorimeter/TileRecUtils/python/TileRecFlags.py b/TileCalorimeter/TileRecUtils/python/TileRecFlags.py index 8f085d31df1447807431bdca5b0b96f04e05eb69..670eda6eff58461bc2b06f9b7746186c90c236a8 100644 --- a/TileCalorimeter/TileRecUtils/python/TileRecFlags.py +++ b/TileCalorimeter/TileRecUtils/python/TileRecFlags.py @@ -96,6 +96,14 @@ class doTileMF(JobProperty): allowedTypes = ['bool'] StoredValue = False +# +class doTileWiener(JobProperty): + """ Use Wiener filter method for energy reconstruction + """ + statusOn = True + allowedTypes = ['bool'] + StoredValue = False + # class noiseFilter(JobProperty): """ appply one or another noise suppression algorithm at the level of raw channels @@ -266,6 +274,7 @@ list_jobproperties = [ doTileManyAmps, doTileMF, doTileOptATLAS, + doTileWiener, TileRawChannelContainer, TileDigitsContainer, TileRunType, diff --git a/TileCalorimeter/TileRecUtils/src/TileRawChannelBuilderWienerFilter.cxx b/TileCalorimeter/TileRecUtils/src/TileRawChannelBuilderWienerFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a2c8454364fc84d2c1e9b660445630ddc32ae231 --- /dev/null +++ b/TileCalorimeter/TileRecUtils/src/TileRawChannelBuilderWienerFilter.cxx @@ -0,0 +1,472 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TileEvent/TileRawChannel.h" +#include "TileCalibBlobObjs/TileCalibUtils.h" + +// Gaudi includes +#include "GaudiKernel/Property.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" + +// Atlas includes +#include "AthAllocators/DataPool.h" +#include "AthenaKernel/errorcheck.h" +#include "xAODEventInfo/EventInfo.h" + +// Tile includes +#include "TileRecUtils/TileRawChannelBuilderWienerFilter.h" +#include "TileConditions/TilePulseShapes.h" +#include "CLHEP/Matrix/Matrix.h" +#include "TileEvent/TileRawChannelContainer.h" +#include "TileEvent/TileDigitsContainer.h" +#include "TileEvent/TileDigits.h" +#include "CaloIdentifier/TileID.h" +#include "TileIdentifier/TileHWID.h" +#include "TileConditions/TileInfo.h" + +//using namespace std; +#include <algorithm> + +//interface stuff +static const InterfaceID IID_ITileRawChannelBuilderWienerFilter("TileRawChannelBuilderWienerFilter", 1, 0); + + +const InterfaceID& TileRawChannelBuilderWienerFilter::interfaceID() { + return IID_ITileRawChannelBuilderWienerFilter; +} + + +#define TILE_WienerFilterBUILDERVERBOSE false + +// initialize Wiener coefficients ( ZeroBias <mu>=40 ) +const float TileRawChannelBuilderWienerFilter::m_gfcWiener[8] = { + -0.194081, + 0.467562, + -1.25846, + 2.18528, + -1.2648, + 0.63341, + -0.276375, + -14.2093 +}; +const float TileRawChannelBuilderWienerFilter::m_ofcWiener[7][8] = { + {0.04382, -0.999, 0.5212, 1.179, -0.8052, 0.4123, -0.1756, -5.393}, + {0.1806, 0.02539, -1.253, 2.187, -1.254, 0.6214, -0.2732, -14.53}, + {-0.3267, 0.6014, -1.346, 2.224, -1.258, 0.6043, -0.276, -14.41}, + {-0.1914, 0.4693, -1.246, 2.169, -1.243, 0.6191, -0.2633, -15.15}, + {-0.1831, 0.4734, -1.253, 2.241, -1.424, 0.9173, -0.5364, -15.43}, + {-0.2245, 0.5627, -1.398, 2.433, -1.722, 1.204, -0.5617, -15.26}, + {-0.2367, 0.617, -1.502, 2.539, -1.729, 0.7092, -0.1435, -14.15} +}; + +TileRawChannelBuilderWienerFilter::TileRawChannelBuilderWienerFilter(const std::string& type, + const std::string& name, const IInterface *parent) + : TileRawChannelBuilder(type, name, parent) + , m_tileToolTiming("TileCondToolTiming") + , m_tileCondToolOfc("TileCondToolOfc") + , m_tileToolNoiseSample("TileCondToolNoiseSample") + , m_bunchCrossingTool("BunchCrossingTool") + , m_nSignal(0) + , m_nNegative(0) + , m_nCenter(0) + , m_nConst(0) + , m_nSamples(0) + , m_t0SamplePosition(0) + , m_maxTime(0.0) + , m_minTime(0.0) +{ + //declare interfaces + declareInterface< TileRawChannelBuilder >( this ); + declareInterface< TileRawChannelBuilderWienerFilter >(this); + + m_TileRawChannelContainerID = "TileRawChannelWiener"; + + //declare properties + declareProperty("TileCondToolTiming", m_tileToolTiming); + declareProperty("TileCondToolOfc", m_tileCondToolOfc ,"TileCondToolOfc"); + declareProperty("TileCondToolNoiseSample", m_tileToolNoiseSample,"TileCondToolNoiseSample"); + declareProperty("BunchCrossingTool", m_bunchCrossingTool); + declareProperty("MaxIterations",m_maxIterations = 5); + declareProperty("PedestalMode",m_pedestalMode = 17); + declareProperty("TimeForConvergence",m_timeForConvergence = 0.5); + declareProperty("ConfTB",m_confTB = false); + declareProperty("Minus1Iteration",m_minus1Iter = false); + declareProperty("AmplitudeCorrection",m_correctAmplitude = false); + declareProperty("TimeCorrection", m_correctTimeNI = false); + declareProperty("BestPhase",m_bestPhase = false); + declareProperty("EmulateDSP",m_emulateDsp = false); + declareProperty("MC",m_isMC = false); +} + + +TileRawChannelBuilderWienerFilter::~TileRawChannelBuilderWienerFilter() { +} + + +StatusCode TileRawChannelBuilderWienerFilter::initialize() { + + ATH_MSG_INFO( "initialize()" ); + + m_rChType = TileFragHash::WienerFilterOffline; // type for offline Wiener Filter + + // init in superclass + CHECK( TileRawChannelBuilder::initialize() ); + + if (m_maxIterations != 1) m_correctTimeNI = false; + + // bits 12-15 - various options + // if (m_correctTimeNI) m_bsflags |= 0x1000; + if (m_correctAmplitude) m_bsflags |= 0x2000; + if (m_maxIterations > 1) m_bsflags |= 0x4000; + if (m_bestPhase) m_bsflags |= 0x8000; + + ATH_MSG_DEBUG( " MaxIterations=" << m_maxIterations + << " PedestalMode=" << m_pedestalMode + << " TimeForConvergence=" << m_timeForConvergence + << " ConfTB=" << m_confTB + << " Minus1Iteration=" << m_minus1Iter + << " AmplitudeCorrection=" << m_correctAmplitude + << " TimeCorrection=" << m_correctTimeNI + << " Best Phase " << m_bestPhase ); + + m_nSamples = m_tileInfo->NdigitSamples(); + m_t0SamplePosition = m_tileInfo->ItrigSample(); + m_maxTime = 25 * (m_nSamples - m_t0SamplePosition - 1); + m_minTime = -25 * m_t0SamplePosition; + ATH_MSG_DEBUG(" NSamples=" << m_nSamples + << " T0Sample=" << m_t0SamplePosition + << " minTime=" << m_minTime + << " maxTime=" << m_maxTime ); + + if (m_pedestalMode % 10 > 2 && m_nSamples != m_pedestalMode % 10) { + if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "Changing PedestalMode from " << m_pedestalMode; + m_pedestalMode = (m_pedestalMode / 10) * 10 + m_nSamples; + if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << " to " << m_pedestalMode << endmsg; + } + + + if (m_nSamples != 7 && (m_pedestalMode == 71 || m_pedestalMode == 7621)) { + ATH_MSG_ERROR( "Incompatable pedestal mode [" << m_pedestalMode + << "] and number of samples [" << m_nSamples << "]" ); + return StatusCode::FAILURE; + } + + m_nSignal = 0; + m_nNegative = 0; + m_nCenter = 0; + m_nConst = 0; + + const IGeoModelSvc *geoModel = 0; + CHECK( service("GeoModelSvc", geoModel) ); + + // dummy parameters for the callback: + int dummyInt = 0; + std::list<std::string> dummyList; + + if (geoModel->geoInitialized()) { + return geoInit(dummyInt, dummyList); + } else { + CHECK( detStore()->regFcn(&IGeoModelSvc::geoInit, geoModel, + &TileRawChannelBuilderWienerFilter::geoInit, this) ); + } + + return StatusCode::SUCCESS; +} + + +StatusCode TileRawChannelBuilderWienerFilter::geoInit(IOVSVC_CALLBACK_ARGS) { + + //=== get TileCondToolOfc + CHECK( m_tileCondToolOfc.retrieve() ); + + //=== get TileCondToolNoiseSample + CHECK( m_tileToolNoiseSample.retrieve() ); + + if (m_bestPhase) { + //=== get TileToolTiming + CHECK( m_tileToolTiming.retrieve() ); + } + + if (m_isMC) { + m_bunchCrossingTool.setTypeAndName("Trig::MCBunchCrossingTool/BunchCrossingTool"); + } else { // is data + m_bunchCrossingTool.setTypeAndName("Trig::LHCBunchCrossingTool/BunchCrossingTool"); + } + //=== get TrigBunchCrossingTool + CHECK( m_bunchCrossingTool.retrieve() ); + + ATH_MSG_INFO( "initialization completed" ); + + return StatusCode::SUCCESS; +} + + +StatusCode TileRawChannelBuilderWienerFilter::finalize() { + + if (msgLvl(MSG::VERBOSE)) { + if (m_maxIterations == 1) { // Without iterations + msg(MSG::VERBOSE) << "Counters: Signal=" << m_nSignal + << " Constant=" << m_nConst + << " Total=" << m_nSignal + m_nConst << endmsg; + } else { + msg(MSG::VERBOSE) << "Counters: Signal=" << m_nSignal + << " Negat=" << m_nNegative + << " Center=" << m_nCenter + << " Constant=" << m_nConst + << " Total=" << m_nSignal + m_nNegative + m_nConst + m_nCenter << endmsg; + } + } + + ATH_MSG_DEBUG( "Finalizing" ); + + return StatusCode::SUCCESS; +} + + +TileRawChannel * TileRawChannelBuilderWienerFilter::rawChannel(const TileDigits* digits) { + + ++m_chCounter; + + double pedestal = 0.; + double energy = 0.; + double time = 0.; + double chi2 = 0.; + m_digits = digits->samples(); + const HWIdentifier adcId = digits->adc_HWID(); + int gain = m_tileHWID->adc(adcId); + + ATH_MSG_VERBOSE( "Building Raw Channel, with WienerFilter, HWID:" << m_tileHWID->to_string(adcId) + << " gain=" << gain ); + + int ros = m_tileHWID->ros(adcId); + int drawer = m_tileHWID->drawer(adcId); + int channel = m_tileHWID->channel(adcId); + chi2 = filter(ros, drawer, channel, gain, pedestal, energy, time); + + if (m_calibrateEnergy) { + energy = m_tileInfo->CisCalib(adcId, energy); + } + + if (msgLvl(MSG::VERBOSE)) { + msg(MSG::VERBOSE) << "Creating WienerFilter RawChannel" + << " a=" << energy + << " t=" << time + << " ped=" << pedestal + << " q=" << chi2 << endmsg; + + msg(MSG::VERBOSE) << "digits:"; + + for (unsigned int i = 0; i < m_digits.size(); ++i) + msg(MSG::VERBOSE) << " " << m_digits[i]; + + msg(MSG::VERBOSE) << " " << endmsg; + } + + // return new TileRawChannel + DataPool<TileRawChannel> tileRchPool(m_dataPoollSize); + TileRawChannel *rawCh = tileRchPool.nextElementPtr(); + rawCh->assign (adcId, + energy, + time, + chi2, + pedestal); + + if (m_correctTime + && (time != 0 + && time < m_maxTime + && time > m_minTime)) { + + rawCh->insertTime(m_tileInfo->TimeCalib(adcId, time)); + ATH_MSG_VERBOSE( "Correcting time, new time=" << rawCh->time() ); + + } + + if (TileID::HIGHGAIN == gain) { + ++m_nChH; + m_RChSumH += energy; + } else { + ++m_nChL; + m_RChSumL += energy; + } + + return rawCh; +} + + +int TileRawChannelBuilderWienerFilter::findMaxDigitPosition() { + + ATH_MSG_VERBOSE( " findMaxDigitPosition()" ); + + int iMaxDigit = 0; + float maxDigit = 0.; + bool saturated = false; + + for (unsigned int i = 0; i < m_digits.size(); i++) { + if (m_digits[i] > 1022.99) saturated = true; + if (maxDigit < m_digits[i]) { + maxDigit = m_digits[i]; + iMaxDigit = i; + } + } + + if (msgLvl(MSG::VERBOSE)) { + for (unsigned int i = 0; i < m_digits.size(); i++) { + msg(MSG::VERBOSE) << " " << m_digits[i]; + } + + msg(MSG::VERBOSE) << "; Max: digit[" << iMaxDigit << "]=" << maxDigit << endmsg; + + if (saturated) msg(MSG::VERBOSE) << " Samples saturated" << endmsg; + } + + return iMaxDigit; +} + + +float TileRawChannelBuilderWienerFilter::getPedestal(int ros, int drawer, int channel, int gain) { + float pedestal = 0.; + + switch (m_pedestalMode) { + case -1: + // use pedestal from conditions DB + pedestal = m_tileToolNoiseSample->getPed(TileCalibUtils::getDrawerIdx(ros, drawer), channel, gain); + break; + case 7: + pedestal = m_digits[6]; + break; + case 9: + pedestal = m_digits[8]; + break; + case 12: + pedestal = .5 * (m_digits[0] + m_digits[1]); + break; + case 17: + pedestal = .5 * (m_digits[0] + m_digits[6]); + break; + case 19: + pedestal = .5 * (m_digits[0] + m_digits[8]); + break; + case 71: + pedestal = std::min(m_digits[0], m_digits[6]); + break; + case 7621: + pedestal = 0.5 * std::min(m_digits[0] + m_digits[1], m_digits[5] + m_digits[6]); + break; + default: + pedestal = m_digits[0]; + break; + } + + ATH_MSG_VERBOSE("getPedestal(): pedestal=" << pedestal); + + return pedestal; +} + +int TileRawChannelBuilderWienerFilter::getBCIDIndex() { + int bcidIndex = -1; + + const xAOD::EventInfo* eventInfo(0); + + if (evtStore()->retrieve(eventInfo).isSuccess()) { + int bcid = eventInfo->bcid(); + int distFront = m_bunchCrossingTool->distanceFromFront(bcid, Trig::IBunchCrossingTool::BunchCrossings); + int distTail = m_bunchCrossingTool->distanceFromTail(bcid, Trig::IBunchCrossingTool::BunchCrossings); + + ATH_MSG_VERBOSE( "EventInfo loaded: " + << " BCID=" << bcid + << " DistFront=" << distFront + << " DistTail=" << distTail); + + if (distFront == -1 || distTail == -1) { + bcidIndex = -1; + } else if (distFront < 3 && distTail > distFront) { + bcidIndex = distFront; + } else if (distTail < 3 && distTail < distFront) { + bcidIndex = 6 - distTail; + } else { + bcidIndex = 3; + } + + } else { + ATH_MSG_VERBOSE("EventInfo not available"); + } + + ATH_MSG_VERBOSE("getBCIDIndex(): bcidIndex=" << bcidIndex); + + return bcidIndex; +} + + +double TileRawChannelBuilderWienerFilter::filter(int ros, int drawer, int channel + , int &gain, double &pedestal, double &litude, double &time) { + + ATH_MSG_VERBOSE( "filter()" ); + + amplitude = 0.; + time = 0.; + double chi2 = 0.; + + auto minMaxDigits = std::minmax_element(m_digits.begin(), m_digits.end()); + float minDigit = *minMaxDigits.first; + float maxDigit = *minMaxDigits.second; + + if (maxDigit - minDigit < 0.01) { // constant value in all samples + + pedestal = minDigit; + chi2 = 0.; + ATH_MSG_VERBOSE( "CASE NO SIGNAL: maxdig-mindig = " << maxDigit << "-" << minDigit + << " = " << maxDigit - minDigit ); + + m_nConst++; + + } else { + float weights[8]; + memset(weights, 0, sizeof(weights)); + + int bcidIndex = getBCIDIndex(); + + if (ros > 1 && channel == 1 && bcidIndex >= 0) { + ATH_MSG_VERBOSE( "Switch to optimal mode"); + for (int wi = 0; wi < 8; wi++) { + weights[wi] = m_ofcWiener[bcidIndex][wi]; + } + } else { + ATH_MSG_VERBOSE( "Switch to general mode"); + for (int wi = 0; wi < 8; wi++) { + weights[wi] = m_gfcWiener[wi]; + } + } + + for (unsigned int i = 0; i < m_digits.size(); i++) { + amplitude += weights[i] * m_digits[i]; // Wiener coefs + } + amplitude += weights[7]; // Wiener bias + + double phase = 0.; + pedestal = getPedestal(ros, drawer, channel, gain); + + chi2 = compute(ros, drawer, channel, gain, pedestal, amplitude, time, phase); + + m_nSignal++; + } + + return chi2; +} + +double TileRawChannelBuilderWienerFilter::compute(int ros, int drawer, int channel, int gain, + double &pedestal, double &litude, double &time, double& phase) { + + ATH_MSG_VERBOSE( "compute();" + << " ros=" << ros + << " drawer=" << drawer + << " channel=" << channel + << " gain=" << gain + << " pedestal=" << pedestal + << " amplitude=" << amplitude + << " time=" << time + << " phase=" << phase ); + + double chi2 = 0.; + return chi2; +} diff --git a/TileCalorimeter/TileRecUtils/src/components/TileRecUtils_entries.cxx b/TileCalorimeter/TileRecUtils/src/components/TileRecUtils_entries.cxx index 4e4ab60d53cf894d7a511a2acbd753a975aab28e..dcb7011dc3280e1cf4868d856c9fc69866af469c 100644 --- a/TileCalorimeter/TileRecUtils/src/components/TileRecUtils_entries.cxx +++ b/TileCalorimeter/TileRecUtils/src/components/TileRecUtils_entries.cxx @@ -8,6 +8,7 @@ #include "TileRecUtils/TileRawChannelBuilderQIEFilter.h" #include "TileRecUtils/TileRawChannelBuilderManyAmps.h" #include "TileRecUtils/TileRawChannelBuilderMF.h" +#include "TileRecUtils/TileRawChannelBuilderWienerFilter.h" #include "TileRecUtils/TileBeamInfoProvider.h" #include "TileRecUtils/TileCellBuilder.h" #include "TileRecUtils/TileCellFakeProb.h" @@ -28,6 +29,7 @@ DECLARE_TOOL_FACTORY( TileRawChannelBuilderOpt2Filter ) DECLARE_TOOL_FACTORY( TileRawChannelBuilderQIEFilter ) DECLARE_TOOL_FACTORY( TileRawChannelBuilderManyAmps ) DECLARE_TOOL_FACTORY( TileRawChannelBuilderMF ) +DECLARE_TOOL_FACTORY( TileRawChannelBuilderWienerFilter ) DECLARE_TOOL_FACTORY( TileBeamInfoProvider ) DECLARE_TOOL_FACTORY( TileCellBuilder ) DECLARE_TOOL_FACTORY( TileCellFakeProb ) @@ -49,6 +51,7 @@ DECLARE_FACTORY_ENTRIES(TileRecUtils) { DECLARE_TOOL( TileRawChannelBuilderQIEFilter ) DECLARE_TOOL( TileRawChannelBuilderManyAmps ) DECLARE_TOOL( TileRawChannelBuilderMF ) + DECLARE_TOOL( TileRawChannelBuilderWienerFilter ) DECLARE_TOOL( TileBeamInfoProvider ) DECLARE_TOOL( TileCellBuilder ) DECLARE_TOOL( TileCellFakeProb ) diff --git a/Tools/PyJobTransforms/python/trfArgClasses.py b/Tools/PyJobTransforms/python/trfArgClasses.py index ae5c8a52323f5557cd4257748969a5c24c1dc00f..b5a93129daf02aaf40e5186325be15fea219d8f2 100644 --- a/Tools/PyJobTransforms/python/trfArgClasses.py +++ b/Tools/PyJobTransforms/python/trfArgClasses.py @@ -695,6 +695,9 @@ class argFile(argList): msg.debug('Found root filesystem input - activating globbing') newValue = [] for filename in self._value: + if str(filename).startswith("root"): + msg.debug('Found input file name starting with "root," setting XRD_RUNFORKHANDLER=1, which enables fork handlers for xrootd in direct I/O') + os.environ["XRD_RUNFORKHANDLER"] = "1" if str(filename).startswith("https") or str(filename).startswith("davs") or not(str(filename).endswith('/')) and '*' not in filename and '?' not in filename: msg.debug('Seems that only one file was given: {0}'.format(filename)) newValue.extend(([filename])) diff --git a/Tracking/TrkVertexFitter/TrkVKalVrtFitter/src/TrkVKalVrtFitter.cxx b/Tracking/TrkVertexFitter/TrkVKalVrtFitter/src/TrkVKalVrtFitter.cxx index dd185760f92f84319fad4709a2a6928d30f4d906..d278059f001dee888c87f97f7a8090d494cea784 100755 --- a/Tracking/TrkVertexFitter/TrkVKalVrtFitter/src/TrkVKalVrtFitter.cxx +++ b/Tracking/TrkVertexFitter/TrkVKalVrtFitter/src/TrkVKalVrtFitter.cxx @@ -53,7 +53,8 @@ TrkVKalVrtFitter:: TrkVKalVrtFitter(const std::string& type, m_useZPointingCnst(false), m_usePassNear(false), m_usePassWithTrkErr(false), - m_useMagFieldRotation(false) + m_useMagFieldRotation(false), + m_ErrMtx(nullptr) { declareInterface<IVertexFitter>(this); declareInterface<ITrkVKalVrtFitter>(this);