diff --git a/LArCalorimeter/LArG4/LArG4Code/CMakeLists.txt b/LArCalorimeter/LArG4/LArG4Code/CMakeLists.txt index 983c95848543042fe0c3eec69be0c64a8c888ca6..e57ac4f4d852cdd6a2f92ce08c8294428e82123a 100644 --- a/LArCalorimeter/LArG4/LArG4Code/CMakeLists.txt +++ b/LArCalorimeter/LArG4/LArG4Code/CMakeLists.txt @@ -9,6 +9,7 @@ atlas_subdir( LArG4Code ) atlas_depends_on_subdirs( PUBLIC Calorimeter/CaloG4Sim Calorimeter/CaloSimEvent + DetectorDescription/AtlasDetDescr LArCalorimeter/LArGeoModel/LArGeoCode LArCalorimeter/LArSimEvent Simulation/G4Atlas/G4AtlasTools @@ -34,11 +35,11 @@ atlas_add_library( LArG4Code PUBLIC_HEADERS LArG4Code INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} DEFINITIONS ${CLHEP_DEFINITIONS} - LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} CaloSimEvent LArGeoCode LArSimEvent CaloG4SimLib G4AtlasToolsLib StoreGateLib SGtests GaudiKernel + LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} AtlasDetDescr CaloSimEvent LArGeoCode LArSimEvent CaloG4SimLib G4AtlasToolsLib StoreGateLib SGtests GaudiKernel PRIVATE_LINK_LIBRARIES CaloIdentifier AthenaKernel CxxUtils MCTruth ) atlas_add_dictionary( LArG4CodeEnums LArG4Code/LArG4EnumDefs.h LArG4Code/selectionEnums.xml INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} - LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} CaloSimEvent LArGeoCode LArSimEvent CaloG4SimLib G4AtlasToolsLib StoreGateLib SGtests GaudiKernel LArG4Code ) + LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} AtlasDetDescr CaloSimEvent LArGeoCode LArSimEvent CaloG4SimLib G4AtlasToolsLib StoreGateLib SGtests GaudiKernel LArG4Code ) diff --git a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/CalibSDTool.h b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/CalibSDTool.h index 7a9c19ee345b31fb250aeef300bdf7e48b44ed58..fe85068457cc0948a61eec9f54a53d9a96324c63 100644 --- a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/CalibSDTool.h +++ b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/CalibSDTool.h @@ -81,6 +81,7 @@ namespace LArG4 const LArHEC_ID* m_larHecID; const LArMiniFCAL_ID* m_larMiniFcalID; const CaloDM_ID* m_caloDmID; + const AtlasDetectorID* m_id_helper; /// @} }; // class CalibSDTool diff --git a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/LArG4CalibSD.h b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/LArG4CalibSD.h index c3a5effa7b897f37121afe69828cf113056d62e0..1e61b68ec700099c000341a8edd5353b525eb1ca 100644 --- a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/LArG4CalibSD.h +++ b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/LArG4CalibSD.h @@ -21,6 +21,7 @@ class LArFCAL_ID; class LArHEC_ID; class LArMiniFCAL_ID; class CaloDM_ID; +class AtlasDetectorID; class ILArCalibCalculatorSvc; @@ -47,7 +48,7 @@ public: G4bool ProcessHits(G4Step* a_step,G4TouchableHistory*) override; /// End of athena event processing - void EndOfAthenaEvent( CaloCalibrationHitContainer* hitContainer ); + void EndOfAthenaEvent( CaloCalibrationHitContainer* hitContainer, CaloCalibrationHitContainer* deadHitContainer=nullptr ); /// Sets the ID helper pointers void setupHelpers( const LArEM_ID* EM , @@ -62,25 +63,13 @@ public: m_caloDmID = caloDm; } + void addDetectorHelper( const AtlasDetectorID* id_helper) { m_id_helper=id_helper; } + /// For other classes that need to call into us... G4bool SpecialHit(G4Step* a_step, const std::vector<G4double>& a_energies); protected: - /// Constructs the calibration hit and saves it to the set - G4bool SimpleHit( const LArG4Identifier& a_ident, const std::vector<double>& energies ); - -protected: - - /// Member variable - the calculator we'll use - ILArCalibCalculatorSvc * m_calculator; - - /// Count the number of invalid hits. - G4int m_numberInvalidHits; - - /// Are we set up to run with PID hits? - G4bool m_doPID; - // We need two types containers for hits: // The set defined below is used to tell us if we've already had a @@ -97,10 +86,24 @@ protected: }; typedef std::set< CaloCalibrationHit*, LessHit > m_calibrationHits_t; + /// Constructs the calibration hit and saves it to the set + G4bool SimpleHit( const LArG4Identifier& a_ident, const std::vector<double>& energies, m_calibrationHits_t& calibrationHits ); + + /// Member variable - the calculator we'll use + ILArCalibCalculatorSvc * m_calculator; + + /// Count the number of invalid hits. + G4int m_numberInvalidHits; + + /// Are we set up to run with PID hits? + G4bool m_doPID; /// The actual set of calibration hits m_calibrationHits_t m_calibrationHits; + /// The actual set of dead material calibration hits + m_calibrationHits_t m_deadCalibrationHits; + /// Helper function for making "real" identifiers from LArG4Identifiers Identifier ConvertID(const LArG4Identifier& a_ident) const; @@ -110,6 +113,7 @@ protected: const LArHEC_ID* m_larHecID; const LArMiniFCAL_ID* m_larMiniFcalID; const CaloDM_ID* m_caloDmID; + const AtlasDetectorID* m_id_helper; }; #endif diff --git a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/SDWrapper.h b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/SDWrapper.h index aab623292337fb896963de1b967747ff4454194c..24d20c28fe93f479d568161e5395a77527f4f698 100644 --- a/LArCalorimeter/LArG4/LArG4Code/LArG4Code/SDWrapper.h +++ b/LArCalorimeter/LArG4/LArG4Code/LArG4Code/SDWrapper.h @@ -58,7 +58,7 @@ namespace LArG4 using SDList_t = std::vector< std::unique_ptr<SDType> >; /// Construct the wrapper from the output collection name - SDWrapper(const std::string& name, const std::string& hitCollectionName); + SDWrapper(const std::string& name, const std::string& hitCollectionName, std::string deadHitCollectionName=""); /// Add an SD to this wrapper void addSD(std::unique_ptr<SDType> sd); @@ -83,6 +83,12 @@ namespace LArG4 /// The hit container handle SG::WriteHandle<HitContainerType> m_hitColl; + /// The hit container name + std::string m_deadHitCollName; + + /// The hit container handle + SG::WriteHandle<HitContainerType> m_deadHitColl; + /// The list of sensitive detectors that I own and manage SDList_t m_sdList; @@ -92,6 +98,9 @@ namespace LArG4 }; // class SDWrapper + template<> + void SDWrapper<LArG4CalibSD, CaloCalibrationHitContainer>::EndOfAthenaEvent(); + } // namespace detail diff --git a/LArCalorimeter/LArG4/LArG4Code/src/CalibSDTool.cc b/LArCalorimeter/LArG4/LArG4Code/src/CalibSDTool.cc index e47f1ca85952443102acc46155b90cbf87fbf6df..ca06c9878a769161897252cb95f8fc2e7983144d 100644 --- a/LArCalorimeter/LArG4/LArG4Code/src/CalibSDTool.cc +++ b/LArCalorimeter/LArG4/LArG4Code/src/CalibSDTool.cc @@ -66,6 +66,8 @@ namespace LArG4 return StatusCode::FAILURE; } + ATH_CHECK(detStore()->retrieve(m_id_helper)); + // No general volume list for SensitiveDetectorBase m_noVolumes = true; @@ -104,6 +106,11 @@ namespace LArG4 auto sd = std::make_unique<LArG4CalibSD>(sdName, calc, m_doPID); sd->setupHelpers(m_larEmID, m_larFcalID, m_larHecID, m_larMiniFcalID, m_caloDmID); + const std::string dead("Dead"); + if(sdName.find(dead)==std::string::npos) { + sd->addDetectorHelper(m_id_helper); + } + // Assign the volumes to the SD if( assignSD( sd.get(), parsedVolumes ).isFailure() ) { // TODO: can I just return NULL here? diff --git a/LArCalorimeter/LArG4/LArG4Code/src/LArG4CalibSD.cc b/LArCalorimeter/LArG4/LArG4Code/src/LArG4CalibSD.cc index b27e455aecbb2468038da8d794c0d63877723dc5..f9a7b3a35da70d98a7ea2f69ac8a993836870ed5 100644 --- a/LArCalorimeter/LArG4/LArG4Code/src/LArG4CalibSD.cc +++ b/LArCalorimeter/LArG4/LArG4Code/src/LArG4CalibSD.cc @@ -15,7 +15,7 @@ #include "G4RunManager.hh" #include "MCTruth/EventInformation.h" - +#include "AtlasDetDescr/AtlasDetectorID.h" #include "G4Step.hh" LArG4CalibSD::LArG4CalibSD(G4String a_name, ILArCalibCalculatorSvc* calc, bool doPID) @@ -28,6 +28,7 @@ LArG4CalibSD::LArG4CalibSD(G4String a_name, ILArCalibCalculatorSvc* calc, bool d , m_larHecID (nullptr) , m_larMiniFcalID (nullptr) , m_caloDmID (nullptr) + , m_id_helper (nullptr) {} LArG4CalibSD::~LArG4CalibSD() @@ -61,10 +62,16 @@ G4bool LArG4CalibSD::ProcessHits(G4Step* a_step,G4TouchableHistory*) return false; } - return SimpleHit( identifier , energies ); + if(m_id_helper) { + Identifier id = this->ConvertID( identifier ); + if(id.is_valid() && m_id_helper->is_lar_dm(id)) { + return SimpleHit( identifier, energies, m_deadCalibrationHits ); + } + } + return SimpleHit( identifier, energies, m_calibrationHits ); } -G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vector<double>& energies ){ +G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vector<double>& energies, m_calibrationHits_t& calibrationHits ){ // retreive particle ID unsigned int particleID = 0; @@ -100,7 +107,7 @@ G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vect // the existing hit. // Look for the key in the hitCollection (this is a binary search). - auto bookmark = m_calibrationHits.lower_bound(hit); + auto bookmark = calibrationHits.lower_bound(hit); // The lower_bound method of a map finds the first element // whose key is not less than the identifier. If this element @@ -113,14 +120,14 @@ G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vect // Equals() is a function defined in LArG4Hit.h; it has the value of // "true" when a LArG4Hit* points to the same identifier. - if (bookmark == m_calibrationHits.end() || + if (bookmark == calibrationHits.end() || !(*bookmark)->Equals(hit)) { // We haven't had a hit in this readout cell before. Add it // to our set. - if (m_calibrationHits.empty() || - bookmark == m_calibrationHits.begin()) { + if (calibrationHits.empty() || + bookmark == calibrationHits.begin()) { // Insert the hit before the first entry in the map. - m_calibrationHits.insert(hit); + calibrationHits.insert(hit); } else { // We'just done a binary search of hitCollection, so we should use // the results of that search to speed up the insertion of a new @@ -130,7 +137,7 @@ G4bool LArG4CalibSD::SimpleHit( const LArG4Identifier& a_ident , const std::vect // bookmark. We therefore want to decrement the bookmark from // the lower_bound search. - m_calibrationHits.insert(--bookmark, hit); + calibrationHits.insert(--bookmark, hit); } } else { // Update the existing hit. @@ -159,24 +166,35 @@ G4bool LArG4CalibSD::SpecialHit(G4Step* a_step, // If we can't calculate the identifier, something is wrong. if (!(m_calculator->Process( a_step, identifier, vtmp, LArG4::kOnlyID))) return false; - return SimpleHit( identifier , a_energies ); + return SimpleHit( identifier , a_energies, m_calibrationHits ); } -void LArG4CalibSD::EndOfAthenaEvent( CaloCalibrationHitContainer * hitContainer ) +void LArG4CalibSD::EndOfAthenaEvent( CaloCalibrationHitContainer * hitContainer, CaloCalibrationHitContainer * deadHitContainer ) { - // Loop through the hits... - for(auto hit : m_calibrationHits) - { - - // Because of the design, we are sure this is going into the right hit container - // Can we actually do this with move? - hitContainer->push_back(hit); - - } // End of loop over hits - - // Clean up + if(verboseLevel>4) { + G4cout << "EndOfAthenaEvent: " << SensitiveDetectorName << " m_deadCalibrationHits.size() = " << m_deadCalibrationHits.size() << G4endl; + } + if(hitContainer) { + // Loop through the hits... + for(auto hit : m_calibrationHits) { + // Because of the design, we are sure this is going into the right hit container + // Can we actually do this with move? + hitContainer->push_back(hit); + } // End of loop over hits + } + // Clean up m_calibrationHits.clear(); + if(deadHitContainer) { + // Loop through the hits... + for(auto hit : m_deadCalibrationHits) { + // Because of the design, we are sure this is going into the right hit container + // Can we actually do this with move? + deadHitContainer->push_back(hit); + } // End of loop over hits + } + // Clean up + m_deadCalibrationHits.clear(); } diff --git a/LArCalorimeter/LArG4/LArG4Code/src/SDWrapper.cc b/LArCalorimeter/LArG4/LArG4Code/src/SDWrapper.cc index 0182d8d6325b2e4be1c60efda72048492855fd36..853338cf20ce5ae7bc6ed37fd68b304dd0e5cbe7 100644 --- a/LArCalorimeter/LArG4/LArG4Code/src/SDWrapper.cc +++ b/LArCalorimeter/LArG4/LArG4Code/src/SDWrapper.cc @@ -29,10 +29,12 @@ namespace LArG4 //------------------------------------------------------------------------- template<class SDType, class HitContainerType> SDWrapper<SDType, HitContainerType>:: - SDWrapper(const std::string& name, const std::string& hitCollectionName) + SDWrapper(const std::string& name, const std::string& hitCollectionName, std::string deadHitCollectionName) : G4VSensitiveDetector(name), m_hitCollName(hitCollectionName), - m_hitColl(hitCollectionName) + m_hitColl(hitCollectionName), + m_deadHitCollName(deadHitCollectionName), + m_deadHitColl(deadHitCollectionName) {} //------------------------------------------------------------------------- @@ -75,6 +77,13 @@ namespace LArG4 } m_hitColl = CxxUtils::make_unique<HitContainerType>(m_hitCollName); } + if(!m_deadHitCollName.empty() && !m_deadHitColl.isValid()) { + if(verboseLevel >= 5) { + G4cout << GetName() << " \tDEBUG\t" << "Initializing hit container: " + << m_deadHitCollName << G4endl; + } + m_deadHitColl = CxxUtils::make_unique<HitContainerType>(m_deadHitCollName); + } } //------------------------------------------------------------------------- @@ -122,6 +131,45 @@ namespace LArG4 } } + template<> + void SDWrapper<LArG4CalibSD, CaloCalibrationHitContainer>:: + EndOfAthenaEvent() + { + if(!m_hitColl.isValid()) { + G4cerr << GetName() << " \tERROR\t" << "Hit collection WriteHandle is " + << "invalid!" << G4endl; + throw std::runtime_error("Invalid hit container WriteHandle: " + + m_hitColl.name()); + } + CaloCalibrationHitContainer* deadHitCollPtr(nullptr); + if(!m_deadHitCollName.empty()) { + if(!m_deadHitColl.isValid()) { + G4cerr << GetName() << " \tERROR\t" << "Dead Hit collection WriteHandle is " + << "invalid!" << G4endl; + throw std::runtime_error("Invalid hit container WriteHandle: " + + m_deadHitColl.name()); + } + deadHitCollPtr = &*m_deadHitColl; + } + // Loop over each SD and fill the container + for(auto& sd : m_sdList) { + sd->EndOfAthenaEvent( &*m_hitColl, deadHitCollPtr ); + } + // Gather frozen shower hits + if(!m_fastSimSDName.empty()) { + auto fastSD = dynamic_cast<LArG4CalibSD*> + ( G4SDManager::GetSDMpointer()->FindSensitiveDetector(m_fastSimSDName) ); + if(fastSD) { + fastSD->EndOfAthenaEvent( &*m_hitColl, deadHitCollPtr ); + } + else { + G4cerr << GetName() << " \tERROR\t" << "Failed to retrieve/cast " + << m_fastSimSDName << G4endl; + throw std::runtime_error("Failed to retrieve/cast " + m_fastSimSDName); + } + } + } + //------------------------------------------------------------------------- // Explit template instantiations //------------------------------------------------------------------------- diff --git a/LArCalorimeter/LArG4/LArG4H6SD/src/LArG4H62004CalibSD.cc b/LArCalorimeter/LArG4/LArG4H6SD/src/LArG4H62004CalibSD.cc index d7aac6723f199849dbc8535c24d8a73f5e47a615..9234cb37862b58104d25b527215058191317ea91 100644 --- a/LArCalorimeter/LArG4/LArG4H6SD/src/LArG4H62004CalibSD.cc +++ b/LArCalorimeter/LArG4/LArG4H6SD/src/LArG4H62004CalibSD.cc @@ -51,7 +51,7 @@ G4bool LArG4H62004CalibSD::ProcessHits(G4Step* a_step,G4TouchableHistory* /*ROhi } } - bool processed = SimpleHit( ident, energies ); + bool processed = SimpleHit( ident, energies, m_calibrationHits ); if(!processed) G4cout<<"LArG4H62004CalibSD name: "<<GetName()<<" failure !!"<<G4endl; return true; } @@ -84,6 +84,6 @@ G4bool LArG4H62004CalibSD::SpecialHit(G4Step* a_step, } } - bool processed = SimpleHit( ident, a_energies ); + bool processed = SimpleHit( ident, a_energies, m_calibrationHits ); return processed; } diff --git a/LArCalorimeter/LArG4/LArG4SD/CMakeLists.txt b/LArCalorimeter/LArG4/LArG4SD/CMakeLists.txt index a0e41afc27a9c1590e21df202770b4c5b78863f6..6862c144102b12f92bf97298ed764c8dcaa1bf29 100644 --- a/LArCalorimeter/LArG4/LArG4SD/CMakeLists.txt +++ b/LArCalorimeter/LArG4/LArG4SD/CMakeLists.txt @@ -19,6 +19,7 @@ find_package( XercesC ) # Component(s) in the package: atlas_add_component( LArG4SD src/*.cc + src/*.cxx src/components/*.cxx INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} CaloG4SimLib GaudiKernel LArG4Code ) diff --git a/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfig.py b/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfig.py index dfcae0fb3abcf5f0259344f399b4204daf4bece0..61260cfb216e0e9f5619fbba8b940775fd86667c 100644 --- a/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfig.py +++ b/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfig.py @@ -115,7 +115,11 @@ def getLArDeadSensitiveDetector(name="LArDeadSensitiveDetector", **kwargs): kwargs.setdefault("ParticleID",simFlags.ParticleID()) kwargs.setdefault("doEscapedEnergy",simFlags.CalibrationRun.get_Value()!='DeadLAr') # No effect currently - kwargs.setdefault("OutputCollectionNames", ["LArCalibrationHitDeadMaterial"]) + outputCollectionName = "LArCalibrationHitDeadMaterial" + from G4AtlasApps.SimFlags import simFlags + if simFlags.CalibrationRun.get_Value() in ['LAr', 'LAr+Tile']: + outputCollectionName = "LArCalibrationHitDeadMaterial_DEAD" + kwargs.setdefault("HitCollectionName", outputCollectionName) return CfgMgr.LArG4__DeadSDTool(name, **kwargs) def getLArEMBSensitiveDetector(name="LArEMBSensitiveDetector", **kwargs): @@ -258,3 +262,8 @@ def getLArMiniFCALSensitiveDetector(name="LArMiniFCALSensitiveDetector", **kwarg def getCalibrationDefaultCalculator(name="CalibrationDefaultCalculator", **kwargs): return CfgMgr.LArG4__CalibrationDefaultCalculator(name, **kwargs) + +def getDeadMaterialCalibrationHitMerger(name="DeadMaterialCalibrationHitMerger", **kwargs): + kwargs.setdefault("InputHits",["LArCalibrationHitDeadMaterial_DEAD","LArCalibrationHitActive_DEAD","LArCalibrationHitInactive_DEAD"]) + kwargs.setdefault("OutputHits","LArCalibrationHitDeadMaterial") + return CfgMgr.LArG4__CalibrationHitMerger(name, **kwargs) diff --git a/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfigDb.py b/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfigDb.py index 952acf3bec8d3118ddb9ac0cf1f807791b55ce57..202821798a4383e08a7abd4189f3517dae9d19c6 100644 --- a/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfigDb.py +++ b/LArCalorimeter/LArG4/LArG4SD/python/LArG4SDConfigDb.py @@ -1,6 +1,6 @@ # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -from AthenaCommon.CfgGetter import addTool, addService +from AthenaCommon.CfgGetter import addTool, addService, addAlgorithm addTool("LArG4SD.LArG4SDConfig.getLArActiveSensitiveDetector","LArActiveSensitiveDetector") addTool("LArG4SD.LArG4SDConfig.getLArDeadSensitiveDetector","LArDeadSensitiveDetector") addTool("LArG4SD.LArG4SDConfig.getLArEMBSensitiveDetector","LArEMBSensitiveDetector") @@ -11,3 +11,4 @@ addTool("LArG4SD.LArG4SDConfig.getLArInactiveSensitiveDetector","LArInactiveSens addTool("LArG4SD.LArG4SDConfig.getLArMiniFCALSensitiveDetector","LArMiniFCALSensitiveDetector") addService("LArG4SD.LArG4SDConfig.getCalibrationDefaultCalculator","CalibrationDefaultCalculator") +addAlgorithm("LArG4SD.LArG4SDConfig.getDeadMaterialCalibrationHitMerger","DeadMaterialCalibrationHitMerger") diff --git a/LArCalorimeter/LArG4/LArG4SD/src/ActiveSDTool.cc b/LArCalorimeter/LArG4/LArG4SD/src/ActiveSDTool.cc index 0f6372e12c64ac9791a605f80c59dac02ab29f9a..64bb15da0d2307621890e6ce067ab1e5d148c446 100644 --- a/LArCalorimeter/LArG4/LArG4SD/src/ActiveSDTool.cc +++ b/LArCalorimeter/LArG4/LArG4SD/src/ActiveSDTool.cc @@ -89,8 +89,9 @@ namespace LArG4 //--------------------------------------------------------------------------- G4VSensitiveDetector* ActiveSDTool::makeSD() { + const std::string deadHitCollName=m_hitCollName+"_DEAD"; // Create the wrapper - auto sdWrapper = new CalibSDWrapper("LArActiveSDWrapper", m_hitCollName); + auto sdWrapper = new CalibSDWrapper("LArActiveSDWrapper", m_hitCollName, deadHitCollName); // Create the SDs. sdWrapper->addSD( makeOneSD( "Barrel::Presampler::Module::Calibration", &*m_bpsmodcalc, m_presBarVolumes ) ); diff --git a/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.cxx b/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.cxx new file mode 100644 index 0000000000000000000000000000000000000000..720a902a42e1aa0a77f32b84c836ca1ba6017335 --- /dev/null +++ b/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.cxx @@ -0,0 +1,147 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "CalibrationHitMerger.h" + +/** Constructor */ +LArG4::CalibrationHitMerger::CalibrationHitMerger( const std::string& name, ISvcLocator* pSvcLocator ) : + ::AthAlgorithm( name, pSvcLocator ), + m_inputHitsSGKeys(), + m_inputHits(), + m_outputHits() +{ + // Input collections StoreGate keys + declareProperty( "InputHits", m_inputHitsSGKeys ); + + // Output collections + declareProperty( "OutputHits", m_outputHits ); +} + + +/** Destructor */ +LArG4::CalibrationHitMerger::~CalibrationHitMerger() +{} + + +/** Athena Algorithm initialize */ +StatusCode LArG4::CalibrationHitMerger::initialize() +{ + ATH_CHECK(setupReadHandleKeyVector(m_inputHitsSGKeys, m_inputHits )); + + ATH_CHECK(initializeVarHandleKey(m_outputHits )); + + return StatusCode::SUCCESS; +} + + +/** Athena Algorithm execute */ +StatusCode LArG4::CalibrationHitMerger::execute() +{ + // skip if not input collection + if ( m_inputHits.empty() ) { + return StatusCode::SUCCESS; + } + // TODO: is there a way to conveniently get the total number of hits in all m_inputHits + // and reserve the corresponding size in the outputHandle + SG::WriteHandle<CaloCalibrationHitContainer> outputHandle{m_outputHits}; + ATH_CHECK( outputHandle.record(std::make_unique<CaloCalibrationHitContainer>()) ); + m_calibrationHits_t calibrationHits; + unsigned int nHitsMerged(0); + for ( const auto& collKey: m_inputHits ) { + SG::ReadHandle<CaloCalibrationHitContainer> inputHandle{collKey}; + ATH_MSG_DEBUG(inputHandle.name() << " has " << inputHandle->size() << " hits."); + for ( const auto& hit: *inputHandle ) { + // If we haven't had a hit in this cell before, create one and add + // it to the hit collection. + + // If we've had a hit in this cell before, then add the energy to + // the existing hit. + + // Look for the key in the hitCollection (this is a binary search). + auto bookmark = calibrationHits.lower_bound(hit); + + // The lower_bound method of a map finds the first element + // whose key is not less than the identifier. If this element + // == our hit, we've found a match. + + // Reminders: + // bookmark = iterator (pointer) into the hitCollection set. + // (*bookmark) = a member of the set, which is a LArG4Hit*. + + // Equals() is a function defined in LArG4Hit.h; it has the value of + // "true" when a LArG4Hit* points to the same identifier. + + if (bookmark == calibrationHits.end() || + !(*bookmark)->Equals(hit)) { + auto&& hitCopy = std::make_unique<CaloCalibrationHit>(*hit); + // We haven't had a hit in this readout cell before. Add it + // to our set. + if (calibrationHits.empty() || + bookmark == calibrationHits.begin()) { + // Insert the hit before the first entry in the map. + calibrationHits.insert(hitCopy.release()); + } else { + // We'just done a binary search of hitCollection, so we should use + // the results of that search to speed up the insertion of a new + // hit into the map. The "insert" method is faster if the new + // entry is right _after_ the bookmark. If we left bookmark + // unchanged, the new entry would go right _before_ the + // bookmark. We therefore want to decrement the bookmark from + // the lower_bound search. + calibrationHits.insert(--bookmark, hitCopy.release()); + } + } else { + ++nHitsMerged; + // Update the existing hit. + (*bookmark)->Add(hit); + } + } + } + + // Loop through the hits... + for(auto hit : calibrationHits) + { + // Can we actually do this with move? + outputHandle->push_back(hit); + } // End of loop over hits + // Clean up + calibrationHits.clear(); + ATH_MSG_DEBUG(outputHandle.name() << " has " << outputHandle->size() << " hits. Merged " << nHitsMerged << " hits."); + return StatusCode::SUCCESS; +} + + +/** Athena Algorithm finalize */ +StatusCode LArG4::CalibrationHitMerger::finalize() +{ + return StatusCode::SUCCESS; +} + +/** Initialize the given VarHandleKey */ +StatusCode LArG4::CalibrationHitMerger::initializeVarHandleKey( SG::VarHandleKey& varHandleKey ) const { + if ( varHandleKey.key().empty() ) + return StatusCode::SUCCESS; + + return varHandleKey.initialize(); +} +/** Setup a vector of ReadHandleKeys for the given vector of string StoreGate Keys */ +StatusCode LArG4::CalibrationHitMerger::setupReadHandleKeyVector( const SGKeyVector_t& sgKeyVec, + ReadHandleKeyVector_t& readHandleVec ) const { + readHandleVec.reserve( sgKeyVec.size() ); + + // convert string StoreGate key to ReadHandleKey + for ( const auto& sgKey: sgKeyVec ) { + readHandleVec.emplace_back( sgKey ); + } + + // initialize all ReadHandleKeys + for ( auto& readHandleKey: readHandleVec ) { + if ( readHandleKey.initialize().isFailure() ) { + return StatusCode::FAILURE; + } + } + + return StatusCode::SUCCESS; +} + diff --git a/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.h b/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.h new file mode 100644 index 0000000000000000000000000000000000000000..1b0feea4a5a44607f38599f3e1511d30071a3809 --- /dev/null +++ b/LArCalorimeter/LArG4/LArG4SD/src/CalibrationHitMerger.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef LARG4SD_CALIBRATIONHITMERGER_H +#define LARG4SD_CALIBRATIONHITMERGER_H 1 + +// STL includes +#include <set> +#include <string> +#include <vector> + +// Framework includes +#include "AthenaBaseComps/AthAlgorithm.h" +#include "StoreGate/WriteHandleKey.h" +#include "CaloSimEvent/CaloCalibrationHitContainer.h" + +namespace LArG4 { + + /** @class CalibrationHitMerger + + @brief Athena Algorithm that merges a given set of CaloCalibrationHitContainers into a single CaloCalibrationHitContainers - based on CollectionMerger by Elmar Ritsch. + + */ + class CalibrationHitMerger final : public AthAlgorithm { + + public: + /** Constructor */ + CalibrationHitMerger( const std::string& name, ISvcLocator* pSvcLocator ); + + /** Destructor */ + virtual ~CalibrationHitMerger(); + + /** Athena algorithm's interface methods */ + virtual StatusCode initialize() override final; + virtual StatusCode execute() override final; + virtual StatusCode finalize() override final; + + private: + class LessHit { + public: + bool operator() ( CaloCalibrationHit* const& p, CaloCalibrationHit* const& q ) const + { + return p->Less(q); + } + }; + typedef std::set< CaloCalibrationHit*, LessHit > m_calibrationHits_t; + + /** Initialize the given VarHandleKey */ + StatusCode initializeVarHandleKey( SG::VarHandleKey& varHandleKey ) const; + + /** Commonly used member and function parameter types */ + typedef std::vector<std::string> SGKeyVector_t; + typedef std::vector<SG::ReadHandleKey<CaloCalibrationHitContainer>> ReadHandleKeyVector_t; + + + /** Setup a vector of ReadHandleKeys for the given vector of string StoreGate Keys */ + StatusCode setupReadHandleKeyVector( const SGKeyVector_t& sgKeyVec, + ReadHandleKeyVector_t& readHandleVec ) const; + + /** Input collection StoreGate keys */ + SGKeyVector_t m_inputHitsSGKeys; + + /** Input collection ReadHandleKeys */ + ReadHandleKeyVector_t m_inputHits; + + /** Output collection WriteHandleKeys */ + SG::WriteHandleKey<CaloCalibrationHitContainer> m_outputHits; + }; + +} + +#endif //> !LARG4SD_CALIBRATIONHITMERGER_H diff --git a/LArCalorimeter/LArG4/LArG4SD/src/InactiveSDTool.cc b/LArCalorimeter/LArG4/LArG4SD/src/InactiveSDTool.cc index f874ed97b7a99a1ef01286e25084058e177202c4..24b1c53ea9fd833a6be2ffdcb38f6a358aeeebdf 100644 --- a/LArCalorimeter/LArG4/LArG4SD/src/InactiveSDTool.cc +++ b/LArCalorimeter/LArG4/LArG4SD/src/InactiveSDTool.cc @@ -84,8 +84,9 @@ namespace LArG4 //--------------------------------------------------------------------------- G4VSensitiveDetector* InactiveSDTool::makeSD() { + const std::string deadHitCollName=m_hitCollName+"_DEAD"; // Create the wrapper - auto sdWrapper = new CalibSDWrapper("LArInactiveSDWrapper", m_hitCollName); + auto sdWrapper = new CalibSDWrapper("LArInactiveSDWrapper", m_hitCollName, deadHitCollName); sdWrapper->addSD( makeOneSD("LAr::Barrel::Presampler::Inactive", &*m_embpscalc, m_barPreVolumes) diff --git a/LArCalorimeter/LArG4/LArG4SD/src/components/LArG4SD_entries.cxx b/LArCalorimeter/LArG4/LArG4SD/src/components/LArG4SD_entries.cxx index f139ae9711804631f270c3ee71155cc5da4e9c11..5b3d73eb9c35d39bde2be2b0bba90259a58c8b12 100644 --- a/LArCalorimeter/LArG4/LArG4SD/src/components/LArG4SD_entries.cxx +++ b/LArCalorimeter/LArG4/LArG4SD/src/components/LArG4SD_entries.cxx @@ -9,6 +9,7 @@ #include "../DeadSDTool.h" #include "../CalibrationDefaultCalculator.h" +#include "../CalibrationHitMerger.h" DECLARE_COMPONENT( LArG4::EMBSDTool ) DECLARE_COMPONENT( LArG4::EMECSDTool ) @@ -20,4 +21,4 @@ DECLARE_COMPONENT( LArG4::InactiveSDTool ) DECLARE_COMPONENT( LArG4::DeadSDTool ) DECLARE_COMPONENT( LArG4::CalibrationDefaultCalculator ) - +DECLARE_COMPONENT( LArG4::CalibrationHitMerger )