diff --git a/Calorimeter/CaloDigiAlgs/CMakeLists.txt b/Calorimeter/CaloDigiAlgs/CMakeLists.txt index 42991aa03cc03af6e51ab161d36d1d61df1a7956..5a4de58a7469a2acb320de9c758ea1aef98ebcac 100644 --- a/Calorimeter/CaloDigiAlgs/CMakeLists.txt +++ b/Calorimeter/CaloDigiAlgs/CMakeLists.txt @@ -9,7 +9,7 @@ atlas_subdir( CaloDigiAlgs ) atlas_add_component( CaloDigiAlgs src/*.cxx src/*.h src/components/*.cxx - LINK_LIBRARIES AthenaBaseComps Identifier StoreGateLib WaveRawEvent FaserCaloSimEvent WaveDigiToolsLib) + LINK_LIBRARIES AthenaBaseComps Identifier FaserCaloIdentifier StoreGateLib WaveRawEvent FaserCaloSimEvent WaveDigiToolsLib) atlas_install_python_modules( python/*.py ) diff --git a/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx b/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx index 1abfcf9f11ecf71c135723f51d799828205ea2be..c54e1e37344d963f28a12f9c9f8b5d86781f93c4 100644 --- a/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx +++ b/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx @@ -2,13 +2,15 @@ #include "Identifier/Identifier.h" -#include <vector> +#include "FaserCaloSimEvent/CaloHitIdHelper.h" + #include <map> #include <utility> CaloWaveformDigiAlg::CaloWaveformDigiAlg(const std::string& name, ISvcLocator* pSvcLocator) - : AthReentrantAlgorithm(name, pSvcLocator) { + : AthReentrantAlgorithm(name, pSvcLocator) +{ } @@ -19,26 +21,25 @@ CaloWaveformDigiAlg::initialize() { // Initalize tools ATH_CHECK( m_digiTool.retrieve() ); - // Set key to read waveform from ATH_CHECK( m_caloHitContainerKey.initialize() ); // Set key to write container ATH_CHECK( m_waveformContainerKey.initialize() ); - // Will eventually depend on the type of detector - // TODO: Vary time at which centre it? - // TODO: Change params compared to scint - // m_kernel = new TF1("PDF", " ROOT::Math::crystalball_pdf(x, -0.9, 10, 4, 900)", 0, 1200); - + // Set up helper + ATH_CHECK(detStore()->retrieve(m_ecalID, "EcalID")); + + // Create CB time kernel and pre-evaluate for number of samples m_kernel = new TF1("PDF", "[4] * ROOT::Math::crystalball_pdf(x, [0],[1],[2],[3])", 0, 1200); - //m_kernel->SetParameters(-0.25,10,4,900); m_kernel->SetParameter(0, m_CB_alpha); m_kernel->SetParameter(1, m_CB_n); m_kernel->SetParameter(2, m_CB_sigma); m_kernel->SetParameter(3, m_CB_mean); m_kernel->SetParameter(4, m_CB_norm); + // Pre-evaluate time kernel for each bin + m_timekernel = m_digiTool->evaluate_timekernel(m_kernel); return StatusCode::SUCCESS; } @@ -55,12 +56,10 @@ CaloWaveformDigiAlg::finalize() { StatusCode CaloWaveformDigiAlg::execute(const EventContext& ctx) const { ATH_MSG_DEBUG("Executing"); - - ATH_MSG_DEBUG("Run: " << ctx.eventID().run_number() - << " Event: " << ctx.eventID().event_number()); + ATH_MSG_DEBUG("Run: " << ctx.eventID().run_number() << " Event: " << ctx.eventID().event_number()); // Find the input HIT collection - SG::ReadHandle<CaloHitCollection> caloHitHandle(m_caloHitContainerKey, ctx); + SG::ReadHandle<CaloHitCollection> caloHitHandle(m_caloHitContainerKey, ctx); ATH_CHECK( caloHitHandle.isValid() ); ATH_MSG_DEBUG("Found ReadHandle for CaloHitCollection " << m_caloHitContainerKey); @@ -75,11 +74,50 @@ CaloWaveformDigiAlg::execute(const EventContext& ctx) const { ATH_MSG_DEBUG("CaloHitCollection found with zero length!"); return StatusCode::SUCCESS; } - - // Digitise the hits - CHECK( m_digiTool->digitise<CaloHitCollection>(caloHitHandle.ptr(), - waveformContainerHandle.ptr(), m_kernel, - std::pair<float, float>(m_base_mean, m_base_rms)) ); + + // Create structure to store pulse for each channel + std::map<Identifier, std::vector<uint16_t>> waveforms = m_digiTool->create_waveform_map(m_ecalID); + + for (const auto& tk : m_timekernel) { + std::map<unsigned int, float> counts; + + // Convolve hit energy with evaluated kernel and sum for each hit id (i.e. channel) + for (const auto& hit : *caloHitHandle) { + counts[hit.identify()] += tk * hit.energyLoss(); + } + + // Subtract count from basleine and add result to correct waveform vector + for (const auto& c : counts) { + + unsigned int baseline = m_digiTool->generate_baseline(m_base_mean, m_base_rms); + int value = baseline - c.second; + + if (value < 0) { + ATH_MSG_WARNING("Found pulse " << c.second << " larger than baseline " << c.first); + value = 0; // Protect against scaling signal above baseline + } + + // Convert hit id to Identifier and store + Identifier id = CaloHitIdHelper::GetHelper()->getIdentifier(c.first); + waveforms[id].push_back(value); + } + } + + + //m_chrono->chronoStop("Digit"); + //m_chrono->chronoStart("Write"); + + // Loop over wavefrom vectors to make and store waveform + unsigned int nsamples = m_digiTool->nsamples(); + for (const auto& w : waveforms) { + RawWaveform* wfm = new RawWaveform(); + wfm->setWaveform(0, w.second); + wfm->setIdentifier(w.first); + wfm->setSamples(nsamples); + waveformContainerHandle->push_back(wfm); + } + + //m_chrono->chronoStop("Write"); ATH_MSG_DEBUG("WaveformsHitContainer " << waveformContainerHandle.name() << "' filled with "<< waveformContainerHandle->size() <<" items"); diff --git a/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.h b/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.h index f99d13b5565712045bcef7507fd04bca6bf0d07a..8eeb0a44eba0dde0ede044036b57406cfcf25efc 100644 --- a/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.h +++ b/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.h @@ -19,11 +19,15 @@ #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" +// Helpers +#include "FaserCaloIdentifier/EcalID.h" + // ROOT #include "TF1.h" // STL #include <string> +#include <vector> class CaloWaveformDigiAlg : public AthReentrantAlgorithm { @@ -48,6 +52,8 @@ class CaloWaveformDigiAlg : public AthReentrantAlgorithm { CaloWaveformDigiAlg &operator=(const CaloWaveformDigiAlg&) = delete; //@} + /** @name Steerable pameters for crystal ball and baseline **/ + //@{ Gaudi::Property<double> m_CB_alpha {this, "CB_alpha", 0, "Alpha of the crystal ball function"}; Gaudi::Property<double> m_CB_n {this, "CB_n", 0, "n of the crystal ball function"}; Gaudi::Property<double> m_CB_mean {this, "CB_mean", 0, "Mean of the crystal ball function"}; @@ -56,10 +62,16 @@ class CaloWaveformDigiAlg : public AthReentrantAlgorithm { Gaudi::Property<double> m_base_mean {this, "base_mean", 0, "Mean of the baseline"}; Gaudi::Property<double> m_base_rms {this, "base_rms", 0, "RMS of the baseline"}; + //@} - /// Kernel PDF - TF1* m_kernel; + /** Kernel PDF and evaluated values **/ + //@{ + TF1* m_kernel; + std::vector<float> m_timekernel; + //@} + /// Detector ID helper + const EcalID* m_ecalID{nullptr}; /** * @name Digitisation tool @@ -89,4 +101,6 @@ class CaloWaveformDigiAlg : public AthReentrantAlgorithm { }; + + #endif // CALODIGIALGS_CALODIGIALG_H diff --git a/Calorimeter/FaserCaloSimEvent/CMakeLists.txt b/Calorimeter/FaserCaloSimEvent/CMakeLists.txt index 9777d4178e6e465f0f57de0c82173b0620fbe46a..2b034a3189207f186984b163c0c5a034bee7f956 100644 --- a/Calorimeter/FaserCaloSimEvent/CMakeLists.txt +++ b/Calorimeter/FaserCaloSimEvent/CMakeLists.txt @@ -18,11 +18,11 @@ atlas_add_library( FaserCaloSimEvent PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} DEFINITIONS ${CLHEP_DEFINITIONS} LINK_LIBRARIES ${CLHEP_LIBRARIES} AthAllocators AthenaKernel CxxUtils GeneratorObjects HitManagement StoreGateLib SGtests - PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} FaserCaloIdentifier ) + PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} FaserCaloIdentifier Identifier) atlas_add_dictionary( FaserCaloSimEventDict FaserCaloSimEvent/CaloSimEventDict.h FaserCaloSimEvent/selection.xml INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} - LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} AthAllocators CxxUtils GeneratorObjects HitManagement StoreGateLib SGtests FaserCaloIdentifier FaserCaloSimEvent ) + LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} AthAllocators CxxUtils GeneratorObjects HitManagement StoreGateLib SGtests FaserCaloIdentifier FaserCaloSimEvent Identifier) diff --git a/Calorimeter/FaserCaloSimEvent/FaserCaloSimEvent/CaloHitIdHelper.h b/Calorimeter/FaserCaloSimEvent/FaserCaloSimEvent/CaloHitIdHelper.h index 5500649bc0c789aa5119503ee357839ee7e11b9e..e94581470c0fa76dddbec99c44aa93ba61484cdb 100644 --- a/Calorimeter/FaserCaloSimEvent/FaserCaloSimEvent/CaloHitIdHelper.h +++ b/Calorimeter/FaserCaloSimEvent/FaserCaloSimEvent/CaloHitIdHelper.h @@ -23,6 +23,11 @@ // This class is singleton and static method and variable are used. #include "CxxUtils/checker_macros.h" + +#include "Identifier/Identifier.h" + +#include "FaserCaloIdentifier/EcalID.h" + ATLAS_NO_CHECK_FILE_THREAD_SAFETY; class CaloHitIdHelper : HitIdHelper { @@ -43,6 +48,8 @@ class CaloHitIdHelper : HitIdHelper { // Left or Right int getModule(const int& hid) const; + Identifier getIdentifier(const int& hid) const; + // // Info packing: int buildHitId(const int, const int) const; @@ -54,6 +61,9 @@ class CaloHitIdHelper : HitIdHelper { // // Initialize the helper, only called by the constructor void Initialize(); + + /// Detector ID helper + const EcalID* m_ecalID{nullptr}; }; #endif // CALOSIMEVENT_CALOHITIDHELPER diff --git a/Calorimeter/FaserCaloSimEvent/src/CaloHitIdHelper.cxx b/Calorimeter/FaserCaloSimEvent/src/CaloHitIdHelper.cxx index eec88553dae53bc6e415b385494b32a7f83645ad..0e98fbd6aa3c1be718b049ab91e74ae92b682ed4 100644 --- a/Calorimeter/FaserCaloSimEvent/src/CaloHitIdHelper.cxx +++ b/Calorimeter/FaserCaloSimEvent/src/CaloHitIdHelper.cxx @@ -6,8 +6,6 @@ #include "FaserCaloSimEvent/CaloHitIdHelper.h" #include "StoreGate/StoreGateSvc.h" -#include "StoreGate/StoreGateSvc.h" -#include "FaserCaloIdentifier/EcalID.h" #include "G4Types.hh" #ifdef G4MULTITHREADED @@ -42,10 +40,9 @@ void CaloHitIdHelper::Initialize() { // determine whether hits were created with an SLHC dictionary // in which case eta module field is expanded. // Need to lock this thread-unsafe retrieval - const EcalID* pix; ServiceHandle<StoreGateSvc> detStore ("DetectorStore", "CaloHitIdHelper"); if (detStore.retrieve().isSuccess()) { - if (detStore->retrieve(pix, "EcalID").isFailure()) { pix = 0; } + if (detStore->retrieve(m_ecalID, "EcalID").isFailure()) { m_ecalID = 0; } } InitializeField("Row", 0, 2); @@ -64,6 +61,14 @@ int CaloHitIdHelper::getModule(const int& hid) const return this->GetFieldValue("Module", hid); } +// identifier +Identifier CaloHitIdHelper::getIdentifier(const int& hid) const +{ + return m_ecalID->pmt_id(getRow(hid), getModule(hid), 0); + +} + + // // Info packing: int CaloHitIdHelper::buildHitId( const int row, diff --git a/Scintillator/ScintDigiAlgs/CMakeLists.txt b/Scintillator/ScintDigiAlgs/CMakeLists.txt index 43695c5f90d96053a8b44fa3ac41c0f4c159ad99..3ebe3d691decc51518eb6f64ecae03efd76aaf73 100644 --- a/Scintillator/ScintDigiAlgs/CMakeLists.txt +++ b/Scintillator/ScintDigiAlgs/CMakeLists.txt @@ -9,7 +9,7 @@ atlas_subdir( ScintDigiAlgs ) atlas_add_component( ScintDigiAlgs src/*.cxx src/*.h src/components/*.cxx - LINK_LIBRARIES AthenaBaseComps Identifier StoreGateLib WaveRawEvent ScintSimEvent WaveDigiToolsLib) + LINK_LIBRARIES AthenaBaseComps Identifier ScintIdentifier StoreGateLib WaveRawEvent ScintSimEvent WaveDigiToolsLib) atlas_install_python_modules( python/*.py ) diff --git a/Scintillator/ScintDigiAlgs/python/ScintDigiAlgsConfig.py b/Scintillator/ScintDigiAlgs/python/ScintDigiAlgsConfig.py index 7f2ba8530575eeb6a6c9b51779c482f84bdfc648..292a19c0890672bb3a1530b080d936c8716a2fff 100644 --- a/Scintillator/ScintDigiAlgs/python/ScintDigiAlgsConfig.py +++ b/Scintillator/ScintDigiAlgs/python/ScintDigiAlgsConfig.py @@ -15,6 +15,13 @@ dict_CB_param["Timing"]=dict(CB_alpha=-0.32, CB_n=65, CB_mean=846, CB_sigma=5.3, dict_CB_param["Veto"]=dict(CB_alpha=-0.38, CB_n=25, CB_mean=815, CB_sigma=7.7, CB_norm = 1000) # copy from Trigger; Veto was not in TestBeam, but in sim "Veto" is the TestBeam Trigger component dict_CB_param["Preshower"]=dict(CB_alpha=-0.32, CB_n=65, CB_mean=846, CB_sigma=5.3, CB_norm = 500) +dict_baseline_params = { + "Trigger" : {"mean" : 15000, "rms" : 3}, + "Timing" : {"mean" : 15000, "rms" : 3}, + "Veto" : {"mean" : 15000, "rms" : 3}, + "Preshower" : {"mean" : 15000, "rms" : 3}, + } + # One stop shopping for normal FASER data def ScintWaveformDigitizationCfg(flags): """ Return all algorithms and tools for Waveform digitization """ @@ -48,8 +55,8 @@ def ScintWaveformDigiCfg(flags, name="ScintWaveformDigiAlg", source="", **kwargs digiAlg.CB_sigma = dict_CB_param[source]["CB_sigma"] digiAlg.CB_norm = dict_CB_param[source]["CB_norm"] - digiAlg.base_mean = 15000 - digiAlg.base_rms = 3 + digiAlg.base_mean = dict_baseline_params[source]["mean"] + digiAlg.base_rms = dict_baseline_params[source]["rms"] kwargs.setdefault("WaveformDigitisationTool", tool) diff --git a/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.cxx b/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.cxx index 91cffd93552d222b90c200cf50fa7842e2b7177a..d5235a92ccdacbc2631e4dafc66a3f9dea48dc9d 100644 --- a/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.cxx +++ b/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.cxx @@ -1,11 +1,8 @@ - #include "ScintWaveformDigiAlg.h" -#include "Identifier/Identifier.h" +#include "ScintSimEvent/ScintHitIdHelper.h" -#include <vector> #include <map> -#include <utility> ScintWaveformDigiAlg::ScintWaveformDigiAlg(const std::string& name, @@ -21,25 +18,28 @@ ScintWaveformDigiAlg::initialize() { // Initalize tools ATH_CHECK( m_digiTool.retrieve() ); - // Set key to read waveform from ATH_CHECK( m_scintHitContainerKey.initialize() ); // Set key to write container ATH_CHECK( m_waveformContainerKey.initialize() ); - // Will eventually depend on the type of detector - // TODO: Vary time at which centre it? - // TODO: Better parameters - + // Set up helpers + ATH_CHECK(detStore()->retrieve(m_vetoID, "VetoID")); + ATH_CHECK(detStore()->retrieve(m_triggerID, "TriggerID")); + ATH_CHECK(detStore()->retrieve(m_preshowerID, "PreshowerID")); - + // Create CB time kernel and pre-evaluate for number of samples m_kernel = new TF1("PDF", "[4] * ROOT::Math::crystalball_pdf(x, [0],[1],[2],[3])", 0, 1200); m_kernel->SetParameter(0, m_CB_alpha); m_kernel->SetParameter(1, m_CB_n); m_kernel->SetParameter(2, m_CB_sigma); m_kernel->SetParameter(3, m_CB_mean); m_kernel->SetParameter(4, m_CB_norm); + + // Pre-evaluate time kernel for each bin + m_timekernel = m_digiTool->evaluate_timekernel(m_kernel); + return StatusCode::SUCCESS; } @@ -55,11 +55,9 @@ ScintWaveformDigiAlg::finalize() { StatusCode ScintWaveformDigiAlg::execute(const EventContext& ctx) const { ATH_MSG_DEBUG("Executing"); + ATH_MSG_DEBUG("Run: " << ctx.eventID().run_number() << " Event: " << ctx.eventID().event_number()); - ATH_MSG_DEBUG("Run: " << ctx.eventID().run_number() - << " Event: " << ctx.eventID().event_number()); - - // Find the input HIT collection + // Find the input HITS collection SG::ReadHandle<ScintHitCollection> scintHitHandle(m_scintHitContainerKey, ctx); ATH_CHECK( scintHitHandle.isValid() ); @@ -70,16 +68,59 @@ ScintWaveformDigiAlg::execute(const EventContext& ctx) const { ATH_CHECK( waveformContainerHandle.record( std::make_unique<RawWaveformContainer>()) ); ATH_MSG_DEBUG("WaveformsContainer '" << waveformContainerHandle.name() << "' initialized"); - + if (scintHitHandle->size() == 0) { ATH_MSG_DEBUG("ScintHitCollection found with zero length!"); return StatusCode::SUCCESS; } + + // Create structure to store pulse for each channel + std::map<Identifier, std::vector<uint16_t>> waveforms; + + auto first = *scintHitHandle->begin(); + if (first.isVeto()) { + waveforms = m_digiTool->create_waveform_map(m_vetoID); + } else if (first.isTrigger()) { + waveforms = m_digiTool->create_waveform_map(m_triggerID); + } else if (first.isPreshower()) { + waveforms = m_digiTool->create_waveform_map(m_preshowerID); + } + + // Loop over time samples + for (const auto& tk : m_timekernel) { + std::map<unsigned int, float> counts; + + // Convolve hit energy with evaluated kernel and sum for each hit id (i.e. channel) + for (const auto& hit : *scintHitHandle) { + counts[hit.identify()] += tk * hit.energyLoss(); + } + + // Subtract count from basleine and add result to correct waveform vector + for (const auto& c : counts) { + + unsigned int baseline = m_digiTool->generate_baseline(m_base_mean, m_base_rms); + int value = baseline - c.second; + + if (value < 0) { + ATH_MSG_WARNING("Found pulse " << c.second << " larger than baseline " << c.first); + value = 0; // Protect against scaling signal above baseline + } + + // Convert hit id to Identifier and store + Identifier id = ScintHitIdHelper::GetHelper()->getIdentifier(c.first); + waveforms[id].push_back(value); + } + } - // Digitise the hits - CHECK( m_digiTool->digitise<ScintHitCollection>(scintHitHandle.ptr(), - waveformContainerHandle.ptr(), m_kernel, - std::pair<float, float>(m_base_mean, m_base_rms)) ); + // Loop over wavefrom vectors to make and store raw waveform + unsigned int nsamples = m_digiTool->nsamples(); + for (const auto& w : waveforms) { + RawWaveform* wfm = new RawWaveform(); + wfm->setWaveform(0, w.second); + wfm->setIdentifier(w.first); + wfm->setSamples(nsamples); + waveformContainerHandle->push_back(wfm); + } ATH_MSG_DEBUG("WaveformsHitContainer " << waveformContainerHandle.name() << "' filled with "<< waveformContainerHandle->size() <<" items"); diff --git a/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.h b/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.h index 9bf7843a1867eeffa4587a39875913ea0685d773..de03370698620986377c695852af07c7d8c79b18 100644 --- a/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.h +++ b/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.h @@ -19,12 +19,21 @@ #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" +//Helpers +#include "ScintIdentifier/VetoID.h" +#include "ScintIdentifier/TriggerID.h" +#include "ScintIdentifier/PreshowerID.h" +#include "ScintSimEvent/ScintHitIdHelper.h" +#include "Identifier/Identifier.h" + + // ROOT #include "TF1.h" // STL #include <string> +#include <vector> class ScintWaveformDigiAlg : public AthReentrantAlgorithm { @@ -50,6 +59,10 @@ class ScintWaveformDigiAlg : public AthReentrantAlgorithm { ScintWaveformDigiAlg &operator=(const ScintWaveformDigiAlg&) = delete; //@} + /// + + /** @name Steerable pameters for crystal ball and baseline **/ + //@{ Gaudi::Property<double> m_CB_alpha {this, "CB_alpha", 0, "Alpha of the crystal ball function"}; Gaudi::Property<double> m_CB_n {this, "CB_n", 0, "n of the crystal ball function"}; Gaudi::Property<double> m_CB_mean {this, "CB_mean", 0, "Mean of the crystal ball function"}; @@ -58,10 +71,20 @@ class ScintWaveformDigiAlg : public AthReentrantAlgorithm { Gaudi::Property<double> m_base_mean {this, "base_mean", 0, "Mean of the baseline"}; Gaudi::Property<double> m_base_rms {this, "base_rms", 0, "RMS of the baseline"}; + //@} - /// Kernel PDF - TF1* m_kernel; + /** Kernel PDF and evaluated values **/ + //@{ + TF1* m_kernel; + std::vector<float> m_timekernel; + //@} + + + /// Detector ID helpers + const VetoID* m_vetoID{nullptr}; + const TriggerID* m_triggerID{nullptr}; + const PreshowerID* m_preshowerID{nullptr}; /** * @name Digitisation tool @@ -91,4 +114,5 @@ class ScintWaveformDigiAlg : public AthReentrantAlgorithm { }; + #endif // SCINTDIGIALGS_SCINTDIGIALG_H diff --git a/Scintillator/ScintSimEvent/CMakeLists.txt b/Scintillator/ScintSimEvent/CMakeLists.txt index 27b63871df2aa95ea230c6be47454573a7c14d16..07224a272694548a6c39740e081059d7652a9d91 100644 --- a/Scintillator/ScintSimEvent/CMakeLists.txt +++ b/Scintillator/ScintSimEvent/CMakeLists.txt @@ -18,11 +18,11 @@ atlas_add_library( ScintSimEvent PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} DEFINITIONS ${CLHEP_DEFINITIONS} LINK_LIBRARIES ${CLHEP_LIBRARIES} AthAllocators AthenaKernel CxxUtils GeneratorObjects HitManagement StoreGateLib SGtests - PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ScintIdentifier ) + PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ScintIdentifier Identifier) atlas_add_dictionary( ScintSimEventDict ScintSimEvent/ScintSimEventDict.h ScintSimEvent/selection.xml INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} - LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} AthAllocators CxxUtils GeneratorObjects HitManagement StoreGateLib SGtests ScintIdentifier ScintSimEvent ) + LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} AthAllocators CxxUtils GeneratorObjects HitManagement StoreGateLib SGtests ScintIdentifier ScintSimEvent Identifier) diff --git a/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitIdHelper.h b/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitIdHelper.h index 2874bac894b15684252de5a531081f338750c10c..233acb37e9a01ff47d8e3f93924e473eebe37f62 100644 --- a/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitIdHelper.h +++ b/Scintillator/ScintSimEvent/ScintSimEvent/ScintHitIdHelper.h @@ -23,6 +23,15 @@ // This class is singleton and static method and variable are used. #include "CxxUtils/checker_macros.h" + +//Helpers +#include "ScintIdentifier/VetoID.h" +#include "ScintIdentifier/TriggerID.h" +#include "ScintIdentifier/PreshowerID.h" + +#include "Identifier/Identifier.h" + + ATLAS_NO_CHECK_FILE_THREAD_SAFETY; class ScintHitIdHelper : HitIdHelper { @@ -43,6 +52,9 @@ class ScintHitIdHelper : HitIdHelper { // Layer/Disk int getPlate(const int& hid) const; + // identifier + Identifier getIdentifier(const int& hid) const; + // // Info packing: int buildHitId(const int, const int, const int) const; @@ -54,6 +66,12 @@ class ScintHitIdHelper : HitIdHelper { // // Initialize the helper, only called by the constructor void Initialize(); + + /// Detector ID helpers + const VetoID* m_vetoID{nullptr}; + const TriggerID* m_triggerID{nullptr}; + const PreshowerID* m_preshowerID{nullptr}; + }; #endif // SCINTSIMEVENT_SCINTHITIDHELPER diff --git a/Scintillator/ScintSimEvent/src/ScintHitIdHelper.cxx b/Scintillator/ScintSimEvent/src/ScintHitIdHelper.cxx index cacdb5d720bfdc7759188481346899d48069d856..5f115d47109690e545267e6cbc561fc5b8e7afdf 100644 --- a/Scintillator/ScintSimEvent/src/ScintHitIdHelper.cxx +++ b/Scintillator/ScintSimEvent/src/ScintHitIdHelper.cxx @@ -6,7 +6,6 @@ #include "ScintSimEvent/ScintHitIdHelper.h" #include "StoreGate/StoreGateSvc.h" -#include "ScintIdentifier/VetoID.h" #include "G4Types.hh" #ifdef G4MULTITHREADED @@ -44,7 +43,9 @@ void ScintHitIdHelper::Initialize() { const VetoID* pix; ServiceHandle<StoreGateSvc> detStore ("DetectorStore", "ScitHitIdHelper"); if (detStore.retrieve().isSuccess()) { - if (detStore->retrieve(pix, "VetoID").isFailure()) { pix = 0; } + if (detStore->retrieve(m_vetoID, "VetoID").isFailure()) { m_vetoID = 0; } + if (detStore->retrieve(m_triggerID, "TriggerID").isFailure()) { m_triggerID = 0; } + if (detStore->retrieve(m_preshowerID, "PreshowerID").isFailure()) { m_preshowerID = 0; } } InitializeField("VetoTriggerPreshower", 0, 2); @@ -87,6 +88,20 @@ int ScintHitIdHelper::getPlate(const int& hid) const return this->GetFieldValue("Plate", hid); } + +// identifier +Identifier ScintHitIdHelper::getIdentifier(const int& hid) const +{ + if (isVeto(hid)) { + return m_vetoID->pmt_id(getStation(hid), getPlate(hid), 0); + } else if (isTrigger(hid)) { + return m_triggerID->pmt_id(getStation(hid), getPlate(hid), 0); + } else if (isPreshower(hid)) { + return m_preshowerID->pmt_id(getStation(hid), getPlate(hid), 0); + } + return Identifier(); +} + // // Info packing: int ScintHitIdHelper::buildHitId(const int veto_trigger_preshower, diff --git a/Waveform/WaveDigiTools/CMakeLists.txt b/Waveform/WaveDigiTools/CMakeLists.txt index 692fdb69bc14451ba5a6a660d011bad5b14b66e5..d7e9fd857b273c764dad780aceebd0d3f58acc3a 100644 --- a/Waveform/WaveDigiTools/CMakeLists.txt +++ b/Waveform/WaveDigiTools/CMakeLists.txt @@ -13,13 +13,12 @@ atlas_add_library( WaveDigiToolsLib WaveDigiTools/*.h src/*.cxx src/*.h PUBLIC_HEADERS WaveDigiTools PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} - LINK_LIBRARIES AthenaBaseComps AthenaKernel GeoPrimitives WaveRawEvent + LINK_LIBRARIES AthenaBaseComps AthenaKernel GeoPrimitives WaveRawEvent Identifier PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ) atlas_add_component( WaveDigiTools src/components/*.cxx INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} - LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps GaudiKernel WaveDigiToolsLib ) - + LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps GaudiKernel WaveDigiToolsLib) diff --git a/Waveform/WaveDigiTools/WaveDigiTools/IWaveformDigitisationTool.h b/Waveform/WaveDigiTools/WaveDigiTools/IWaveformDigitisationTool.h index 7241e8167d36facc42748141b58f5b640b4d33ee..c30351902a1b79e9a58ad33d5f58a5d04ed13faa 100644 --- a/Waveform/WaveDigiTools/WaveDigiTools/IWaveformDigitisationTool.h +++ b/Waveform/WaveDigiTools/WaveDigiTools/IWaveformDigitisationTool.h @@ -23,10 +23,15 @@ #include "WaveRawEvent/RawWaveformContainer.h" #include "WaveRawEvent/RawWaveform.h" +#include "Identifier/Identifier.h" + #include "TF1.h" #include "TRandom3.h" #include <utility> +#include <map> +#include <vector> + ///Interface for waveform digitisation tools class IWaveformDigitisationTool : virtual public IAlgTool @@ -42,19 +47,25 @@ public: virtual ~IWaveformDigitisationTool() = default; - // Digitise HITS to Raw waveform - template<class CONT> - StatusCode digitise(const CONT* hitCollection, - RawWaveformContainer* waveContainer, - TF1* kernel, std::pair<float, float> base - ) const; + /// Evaluate time kernel over time samples + virtual std::vector<float> evaluate_timekernel(TF1* kernel) const = 0; + + /// Generate random baseline + virtual unsigned int generate_baseline(int mean, int rms) const = 0; + + /// Create structure to store pulse for each channel + template <class T> + std::map<Identifier, std::vector<uint16_t>> create_waveform_map(const T* idHelper) const; + + /// Number of time samples + unsigned int nsamples() const { return m_nsamples; } private: ServiceHandle<IMessageSvc> m_msgSvc; protected: TRandom3* m_random; - + unsigned int m_nsamples; }; #include "WaveDigiTools/IWaveformDigitisationTool.icc" diff --git a/Waveform/WaveDigiTools/WaveDigiTools/IWaveformDigitisationTool.icc b/Waveform/WaveDigiTools/WaveDigiTools/IWaveformDigitisationTool.icc index b07e1836ac5cedfefa87a8fcbe8c910de886693c..41b8c2650319a448df63d11e098fc8d0784dc056 100644 --- a/Waveform/WaveDigiTools/WaveDigiTools/IWaveformDigitisationTool.icc +++ b/Waveform/WaveDigiTools/WaveDigiTools/IWaveformDigitisationTool.icc @@ -1,62 +1,17 @@ -#include <vector> -#include <map> +#include "Identifier/Identifier.h" +#include "Identifier/ExpandedIdentifier.h" -template<class CONT> -StatusCode IWaveformDigitisationTool::digitise(const CONT* hitCollection, - RawWaveformContainer* container, TF1* kernel, - std::pair<float, float> base) const { +template <class ID> +std::map<Identifier, std::vector<uint16_t>> IWaveformDigitisationTool::create_waveform_map(const ID* idHelper) const { + std::map<Identifier, std::vector<uint16_t>> waveforms; - // Check the container - if (!container) { - MsgStream log(&(*m_msgSvc), name()); - log << MSG::ERROR << "HitCollection passed to digitise() is null!" << endmsg; - return StatusCode::FAILURE; + for (auto itr = idHelper->pmt_begin(); itr != idHelper->pmt_end(); ++itr) { + const ExpandedIdentifier& extId = *itr; + Identifier id = idHelper->pmt_id(extId); + waveforms[id] = std::vector<uint16_t>(); + waveforms[id].reserve(m_nsamples); } - unsigned int size = 600; // TODO: how know the correct number of time samples? - std::vector<float> time(size); - for (unsigned int i=0; i<size; i++) time[i] = 2.*i; - - std::map<unsigned int, std::vector<uint16_t>> waveforms; - //unsigned int baseline = 800; - - // TODO: varying time to centre of edge of bin (odd = centre, even = edge) - - // Loop over time samples - for (const auto& t : time) { - std::map<unsigned int, float> counts; - - unsigned int baseline = m_random->Gaus(base.first, base.second); - - // Convolve hit energy with kernel and sum for each ID (i.e. channel) - for (const auto& hit : *hitCollection) { - counts[hit.identify()] += kernel->Eval(t) * hit.energyLoss(); - //std::cout << "HIT " << hit.identify() << " @ " << t << ": " << kernel->Eval(t) << " " << hit.energyLoss() << " -> " << counts[hit.identify()] << std::endl; - } - - // Add count to correct waveform vec - for (const auto& c : counts) { - int value = baseline - c.second; - if (value < 0) { - MsgStream log(&(*m_msgSvc), name()); - log << MSG::WARNING << "Found pulse " << c.second << " larger than baseline " << c.first << endmsg; - value = 0; // Protect against scaling signal above baseline - } - waveforms[c.first].push_back(value); - //std::cout << "ADC " << c.first << " @ " << t << ": " << baseline - c.second << std::endl; - } - } - - // Loop over wavefrom vecs to make and store waveform - for (const auto& w : waveforms) { - RawWaveform* wfm = new RawWaveform(); - wfm->setWaveform(0, w.second); - wfm->setIdentifier(Identifier(w.first)); - wfm->setSamples(size); - container->push_back(wfm); - } - - - return StatusCode::SUCCESS; + return waveforms; } diff --git a/Waveform/WaveDigiTools/src/WaveformDigitisationTool.cxx b/Waveform/WaveDigiTools/src/WaveformDigitisationTool.cxx index 1c71fe193105f089bec81a5821d4a5558cdb39ca..c62d7f8a753490907bd1e8a513cad5341a2a46be 100644 --- a/Waveform/WaveDigiTools/src/WaveformDigitisationTool.cxx +++ b/Waveform/WaveDigiTools/src/WaveformDigitisationTool.cxx @@ -20,8 +20,28 @@ WaveformDigitisationTool::WaveformDigitisationTool(const std::string& type, cons StatusCode WaveformDigitisationTool::initialize() { ATH_MSG_INFO( name() << "::initalize()" ); + + m_nsamples = 600; m_random = new TRandom3(); + return StatusCode::SUCCESS; } +std::vector<float> +WaveformDigitisationTool::evaluate_timekernel(TF1* kernel) const { + + std::vector<float> timekernel; + timekernel.reserve(m_nsamples); + + for (unsigned int i=0; i<m_nsamples; i++) { + timekernel.push_back(kernel->Eval(2.*i)); + } + + return timekernel; +} + +unsigned int +WaveformDigitisationTool::generate_baseline(int mean, int rms) const { + return m_random->Gaus(mean, rms); +} diff --git a/Waveform/WaveDigiTools/src/WaveformDigitisationTool.h b/Waveform/WaveDigiTools/src/WaveformDigitisationTool.h index 8a5ba71f3dd124fcdd2c6b4b8124ee96591512da..e2dd5169152845824927baeeae7ce8fc36ab46f8 100644 --- a/Waveform/WaveDigiTools/src/WaveformDigitisationTool.h +++ b/Waveform/WaveDigiTools/src/WaveformDigitisationTool.h @@ -28,6 +28,13 @@ class WaveformDigitisationTool: public extends<AthAlgTool, IWaveformDigitisation /// Retrieve the necessary services in initialize StatusCode initialize(); + /// Evaluate time kernel over samples + std::vector<float> evaluate_timekernel(TF1* kernel) const; + + /// Generate random baseline + unsigned int generate_baseline(int mean, int rms) const; + + private: // None diff --git a/Waveform/WaveRecAlgs/src/RawWaveformRecAlg.cxx b/Waveform/WaveRecAlgs/src/RawWaveformRecAlg.cxx index 97f122e50f51c17f2ac3f0e0ff3174cf2f337347..3248939a0879178789e7c770fb584fc0b85cce07 100644 --- a/Waveform/WaveRecAlgs/src/RawWaveformRecAlg.cxx +++ b/Waveform/WaveRecAlgs/src/RawWaveformRecAlg.cxx @@ -52,6 +52,13 @@ RawWaveformRecAlg::execute(const EventContext& ctx) const { ATH_CHECK( waveformHandle.isValid() ); ATH_MSG_DEBUG("Found ReadHandle for RawWaveformContainer " << m_waveformContainerKey); + // Find the output waveform container + SG::WriteHandle<xAOD::WaveformHitContainer> hitContainerHandle(m_waveformHitContainerKey, ctx); + ATH_CHECK( hitContainerHandle.record( std::make_unique<xAOD::WaveformHitContainer>(), + std::make_unique<xAOD::WaveformHitAuxContainer>() ) ); + + ATH_MSG_DEBUG("WaveformsHitContainer '" << hitContainerHandle.name() << "' initialized"); + if (waveformHandle->size() == 0) { ATH_MSG_DEBUG("Waveform container found with zero length!"); return StatusCode::SUCCESS; @@ -69,12 +76,6 @@ RawWaveformRecAlg::execute(const EventContext& ctx) const { ATH_MSG_WARNING("Didn't find ReadHandle for WaveformClock!"); } - // Find the output waveform container - SG::WriteHandle<xAOD::WaveformHitContainer> hitContainerHandle(m_waveformHitContainerKey, ctx); - ATH_CHECK( hitContainerHandle.record( std::make_unique<xAOD::WaveformHitContainer>(), - std::make_unique<xAOD::WaveformHitAuxContainer>() ) ); - - ATH_MSG_DEBUG("WaveformsHitContainer '" << hitContainerHandle.name() << "' initialized"); // Reconstruct all waveforms CHECK( m_recoTool->reconstructAll(*waveformHandle, clockptr, hitContainerHandle.ptr()) );