From 1e6439abd505c4c8d64426d15d57b5a2d89ef9a7 Mon Sep 17 00:00:00 2001 From: Eric Torrence <eric.torrence@cern.ch> Date: Tue, 6 Dec 2022 09:10:45 +0100 Subject: [PATCH] Add WaveformDigiConditionsTool and use this to set digitization parameters --- .../CaloDigiAlgs/python/CaloDigiAlgsConfig.py | 24 ++- .../CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx | 41 +++-- .../CaloDigiAlgs/src/CaloWaveformDigiAlg.h | 28 +-- .../Digitization/scripts/faser_digi.py | 7 +- .../python/ScintDigiAlgsConfig.py | 46 ++--- .../src/ScintWaveformDigiAlg.cxx | 37 ++-- .../ScintDigiAlgs/src/ScintWaveformDigiAlg.h | 25 ++- .../WaveCondUtils/scripts/makeDigiDB.py | 156 ++++++++++++++++ .../IWaveformDigiConditionsTool.h | 63 +++++++ .../python/WaveformDigitizationConfig.py | 21 +++ .../src/WaveformDigiConditionsTool.cxx | 173 ++++++++++++++++++ .../src/WaveformDigiConditionsTool.h | 95 ++++++++++ .../src/WaveformTimingTool.h | 2 +- .../WaveformConditionsTools_entries.cxx | 2 + 14 files changed, 616 insertions(+), 104 deletions(-) create mode 100755 Waveform/WaveformConditions/WaveCondUtils/scripts/makeDigiDB.py create mode 100644 Waveform/WaveformConditions/WaveformConditionsTools/WaveformConditionsTools/IWaveformDigiConditionsTool.h create mode 100644 Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformDigitizationConfig.py create mode 100644 Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformDigiConditionsTool.cxx create mode 100644 Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformDigiConditionsTool.h diff --git a/Calorimeter/CaloDigiAlgs/python/CaloDigiAlgsConfig.py b/Calorimeter/CaloDigiAlgs/python/CaloDigiAlgsConfig.py index c9ae1487..816da133 100644 --- a/Calorimeter/CaloDigiAlgs/python/CaloDigiAlgsConfig.py +++ b/Calorimeter/CaloDigiAlgs/python/CaloDigiAlgsConfig.py @@ -7,6 +7,7 @@ from AthenaConfiguration.ComponentFactory import CompFactory from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg from WaveformConditionsTools.WaveformCableMappingConfig import WaveformCableMappingCfg +#from WaveformConditionsTools.WaveformDigitizationConfig import WaveformDigitizationCfg # One stop shopping for normal FASER data def CaloWaveformDigitizationCfg(flags, **kwargs): @@ -19,6 +20,13 @@ def CaloWaveformDigitizationCfg(flags, **kwargs): acc.merge(CaloWaveformDigiCfg(flags, "CaloWaveformDigiAlg", **kwargs)) acc.merge(CaloWaveformDigitizationOutputCfg(flags)) acc.merge(WaveformCableMappingCfg(flags)) + #acc.merge(WaveformDigitizationCfg(flags)) + + # Just do this here for now + dbInstance = kwargs.get("dbInstance", "TRIGGER_OFL") + dbFolder = kwargs.get("dbFolder", "/WAVE/Digitization") + from IOVDbSvc.IOVDbSvcConfig import addFolders + acc.merge(addFolders(flags, dbFolder, dbInstance, className="CondAttrListCollection")) return acc @@ -29,24 +37,14 @@ def CaloWaveformDigiCfg(flags, name="CaloWaveformDigiAlg", **kwargs): tool = CompFactory.WaveformDigitisationTool(name="CaloWaveformDigtisationTool") kwargs.setdefault("WaveformDigitisationTool", tool) + + tool = CompFactory.WaveformDigiConditionsTool(name="CaloDigiConditionsTool", Detector="Calo") + kwargs.setdefault("DigiConditionsTool", tool) kwargs.setdefault("CaloHitContainerKey", "EcalHits") kwargs.setdefault("WaveformContainerKey", "CaloWaveforms") - kwargs.setdefault("CB_alpha", -0.32) - kwargs.setdefault("CB_n", 1000) - kwargs.setdefault("CB_sigma", 3.67) - kwargs.setdefault("CB_mean", 820) # Time in ns - # This number is over-ridden in the digitization script, so change it there! - kwargs.setdefault("CB_norm", 5.0) # Low gain default without filters, use x5? for high gain - - kwargs.setdefault("base_mean", 15650) - kwargs.setdefault("base_rms", 3) - digiAlg = CompFactory.CaloWaveformDigiAlg(name, **kwargs) - print(f"CaloWaveformDigiAlg normalization: {digiAlg.CB_norm}") - print(f"CaloWaveformDigiAlg mean time: {digiAlg.CB_mean}") - acc.addEventAlgo(digiAlg) return acc diff --git a/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx b/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx index 3e10288e..a44c0d2b 100644 --- a/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx +++ b/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.cxx @@ -16,11 +16,12 @@ CaloWaveformDigiAlg::CaloWaveformDigiAlg(const std::string& name, StatusCode CaloWaveformDigiAlg::initialize() { - ATH_MSG_INFO(name() << "::initalize()" ); + ATH_MSG_INFO(name() << "::initalize()"); // Initalize tools ATH_CHECK( m_digiTool.retrieve() ); ATH_CHECK( m_mappingTool.retrieve() ); + ATH_CHECK( m_digiCondTool.retrieve() ); // Set key to read waveform from ATH_CHECK( m_caloHitContainerKey.initialize() ); @@ -31,16 +32,8 @@ CaloWaveformDigiAlg::initialize() { // 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->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); + // Need to set this on first event + m_kernel = 0; return StatusCode::SUCCESS; } @@ -49,7 +42,8 @@ StatusCode CaloWaveformDigiAlg::finalize() { ATH_MSG_INFO(name() << "::finalize()"); - delete m_kernel; + if (m_kernel) + delete m_kernel; return StatusCode::SUCCESS; } @@ -60,7 +54,7 @@ CaloWaveformDigiAlg::execute(const EventContext& ctx) const { 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); @@ -76,6 +70,27 @@ CaloWaveformDigiAlg::execute(const EventContext& ctx) const { return StatusCode::SUCCESS; } + if (!m_kernel) { + + ATH_MSG_INFO("Setting up calo digitization kernel"); + + // Set up waveform shape + m_kernel = new TF1("PDF", "[4] * ROOT::Math::crystalball_pdf(x, [0],[1],[2],[3])", 0, 1200); + + m_kernel->SetParameter(0, m_digiCondTool->cb_alpha(ctx)); + m_kernel->SetParameter(1, m_digiCondTool->cb_n(ctx)); + m_kernel->SetParameter(2, m_digiCondTool->cb_sigma(ctx)); + m_kernel->SetParameter(3, m_digiCondTool->cb_mean(ctx)); + m_kernel->SetParameter(4, m_digiCondTool->cb_norm(ctx)); + + // Pre-evaluate time kernel for each bin + m_timekernel = m_digiTool->evaluate_timekernel(m_kernel); + + // Also save the baseline parameters + m_base_mean = m_digiCondTool->base_mean(ctx); + m_base_rms = m_digiCondTool->base_rms(ctx); + } + // Create structure to store pulse for each channel std::map<Identifier, std::vector<uint16_t>> waveforms = m_digiTool->create_waveform_map(m_ecalID); diff --git a/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.h b/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.h index 25111bc9..7ee25a27 100644 --- a/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.h +++ b/Calorimeter/CaloDigiAlgs/src/CaloWaveformDigiAlg.h @@ -11,6 +11,7 @@ // Tool classes #include "WaveDigiTools/IWaveformDigitisationTool.h" #include "WaveformConditionsTools/IWaveformCableMappingTool.h" +#include "WaveformConditionsTools/IWaveformDigiConditionsTool.h" // Handles #include "StoreGate/ReadHandleKey.h" @@ -30,7 +31,7 @@ #include <string> #include <vector> -class CaloWaveformDigiAlg : public AthReentrantAlgorithm { +class CaloWaveformDigiAlg: public AthReentrantAlgorithm { public: // Constructor @@ -53,22 +54,15 @@ 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"}; - Gaudi::Property<double> m_CB_sigma {this, "CB_sigma", 0, "Sigma of the crystal ball function"}; - Gaudi::Property<double> m_CB_norm {this, "CB_norm", 0, "Norm of the crystal ball function"}; - - 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"}; - //@} + // We use these a lot, so read them once from the conditions tool + mutable float m_base_mean; + mutable float m_base_rms; /** Kernel PDF and evaluated values **/ + // Mark these mutable, as they must be changed on first event... //@{ - TF1* m_kernel; - std::vector<float> m_timekernel; + mutable TF1* m_kernel; + mutable std::vector<float> m_timekernel; //@} /// Detector ID helper @@ -86,6 +80,12 @@ class CaloWaveformDigiAlg : public AthReentrantAlgorithm { ToolHandle<IWaveformCableMappingTool> m_mappingTool {this, "WaveformCableMappingTool", "WaveformCableMappingTool"}; + /** + * @name Digitization parameters tool + */ + ToolHandle<IWaveformDigiConditionsTool> m_digiCondTool + {this, "DigiConditionsTool", "CaloDigiConditionsTool"}; + /** * @name Input HITS using SG::ReadHandleKey */ diff --git a/Control/CalypsoExample/Digitization/scripts/faser_digi.py b/Control/CalypsoExample/Digitization/scripts/faser_digi.py index 40fb1915..2405432c 100755 --- a/Control/CalypsoExample/Digitization/scripts/faser_digi.py +++ b/Control/CalypsoExample/Digitization/scripts/faser_digi.py @@ -126,12 +126,9 @@ acc.merge(FaserGeometryCfg(ConfigFlags)) from FaserSCT_Digitization.FaserSCT_DigitizationConfigNew import FaserSCT_DigitizationCfg acc.merge(FaserSCT_DigitizationCfg(ConfigFlags)) +# Pass something to set folder tag from CaloDigiAlgs.CaloDigiAlgsConfig import CaloWaveformDigitizationCfg -if args.highCaloGain: - calo_norm = 25. -else: - calo_norm = 5. -acc.merge(CaloWaveformDigitizationCfg(ConfigFlags, CB_norm=calo_norm)) +acc.merge(CaloWaveformDigitizationCfg(ConfigFlags)) from ScintDigiAlgs.ScintDigiAlgsConfig import ScintWaveformDigitizationCfg acc.merge(ScintWaveformDigitizationCfg(ConfigFlags)) diff --git a/Scintillator/ScintDigiAlgs/python/ScintDigiAlgsConfig.py b/Scintillator/ScintDigiAlgs/python/ScintDigiAlgsConfig.py index 407ab913..7f65467a 100644 --- a/Scintillator/ScintDigiAlgs/python/ScintDigiAlgsConfig.py +++ b/Scintillator/ScintDigiAlgs/python/ScintDigiAlgsConfig.py @@ -7,29 +7,8 @@ from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg from WaveformConditionsTools.WaveformCableMappingConfig import WaveformCableMappingCfg -# Crystallball parameter dictionary used in simulated digitized wave reconstruction. -# Crystalball function Parameters estimated from Deion's slides uploaded at -# https://indico.cern.ch/event/1099652/contributions/4626975/attachments/2352595/4013927/Faser-Physics-run3933-plots.pdf (20/01/2022) -# Parameters are per scintillator source, but not per channel. -# Updated aamplitudes (norm) to match testbeam response -# Make everything except VetoNu look like the preshower -dict_CB_param = {} -dict_CB_param["Trigger"]=dict(CB_alpha=-0.424, CB_n=6.14, CB_mean=815, CB_sigma=3.21, CB_norm = 4240) -dict_CB_param["Timing"] =dict(CB_alpha=-0.424, CB_n=6.14, CB_mean=846, CB_sigma=3.21, CB_norm = 4240) -dict_CB_param["Veto"] =dict(CB_alpha=-0.32, CB_n=9.0, CB_mean=815, CB_sigma=3.35, CB_norm = 6840) -dict_CB_param["VetoNu"] =dict(CB_alpha=-0.28, CB_n=1000, CB_mean=815, CB_sigma=5.00, CB_norm = 7040) -dict_CB_param["Preshower"]=dict(CB_alpha=-0.32, CB_n=1000, CB_mean=846, CB_sigma=4.0, CB_norm = 400) - -dict_baseline_params = { - "Trigger" : {"mean" : 15650, "rms" : 3}, - "Timing" : {"mean" : 15650, "rms" : 3}, - "Veto" : {"mean" : 15650, "rms" : 3}, - "VetoNu" : {"mean" : 15650, "rms" : 3}, - "Preshower" : {"mean" : 15650, "rms" : 3}, - } - # One stop shopping for normal FASER data -def ScintWaveformDigitizationCfg(flags): +def ScintWaveformDigitizationCfg(flags, **kwargs): """ Return all algorithms and tools for Waveform digitization """ acc = ComponentAccumulator() @@ -47,6 +26,13 @@ def ScintWaveformDigitizationCfg(flags): acc.merge(ScintWaveformDigitizationOutputCfg(flags)) acc.merge(WaveformCableMappingCfg(flags)) + + # Just do this here for now + dbInstance = kwargs.get("dbInstance", "TRIGGER_OFL") + dbFolder = kwargs.get("dbFolder", "/WAVE/Digitization") + from IOVDbSvc.IOVDbSvcConfig import addFolders + acc.merge(addFolders(flags, dbFolder, dbInstance, className="CondAttrListCollection")) + return acc # Return configured digitization algorithm from SIM hits @@ -56,27 +42,19 @@ def ScintWaveformDigiCfg(flags, name="ScintWaveformDigiAlg", source="", **kwargs acc = ComponentAccumulator() tool = CompFactory.WaveformDigitisationTool(name=source+"WaveformDigtisationTool", **kwargs) + kwargs.setdefault("WaveformDigitisationTool", tool) kwargs.setdefault("ScintHitContainerKey", source+"Hits") kwargs.setdefault("WaveformContainerKey", source+"Waveforms") - digiAlg = CompFactory.ScintWaveformDigiAlg(name, **kwargs) - if "TB" in flags.GeoModel.FaserVersion and source == "Veto": # The testbeam counters were actually VetoNu, so use those parameters source = "VetoNu" - digiAlg.CB_alpha = dict_CB_param[source]["CB_alpha"] - digiAlg.CB_n = dict_CB_param[source]["CB_n"] - digiAlg.CB_mean = dict_CB_param[source]["CB_mean"] - digiAlg.CB_sigma = dict_CB_param[source]["CB_sigma"] - digiAlg.CB_norm = dict_CB_param[source]["CB_norm"] - - digiAlg.base_mean = dict_baseline_params[source]["mean"] - digiAlg.base_rms = dict_baseline_params[source]["rms"] - - kwargs.setdefault("WaveformDigitisationTool", tool) + tool = CompFactory.WaveformDigiConditionsTool(name=source+"CaloDigiConditionsTool", Detector=source) + kwargs.setdefault("DigiConditionsTool", tool) + digiAlg = CompFactory.ScintWaveformDigiAlg(name, **kwargs) acc.addEventAlgo(digiAlg) return acc diff --git a/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.cxx b/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.cxx index 7eb12286..cacda620 100644 --- a/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.cxx +++ b/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.cxx @@ -18,6 +18,7 @@ ScintWaveformDigiAlg::initialize() { // Initalize tools ATH_CHECK( m_digiTool.retrieve() ); ATH_CHECK( m_mappingTool.retrieve() ); + ATH_CHECK( m_digiCondTool.retrieve() ); // Set key to read waveform from ATH_CHECK( m_scintHitContainerKey.initialize() ); @@ -31,16 +32,8 @@ ScintWaveformDigiAlg::initialize() { 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); + // Need to set this on first event + m_kernel = 0; return StatusCode::SUCCESS; } @@ -49,7 +42,8 @@ StatusCode ScintWaveformDigiAlg::finalize() { ATH_MSG_INFO(name() << "::finalize()"); - delete m_kernel; + if (m_kernel) + delete m_kernel; return StatusCode::SUCCESS; } @@ -75,6 +69,27 @@ ScintWaveformDigiAlg::execute(const EventContext& ctx) const { ATH_MSG_DEBUG("ScintHitCollection found with zero length!"); return StatusCode::SUCCESS; } + + if (!m_kernel) { + + ATH_MSG_INFO("Setting up digitization kernel"); + + // Set up waveform shape + m_kernel = new TF1("PDF", "[4] * ROOT::Math::crystalball_pdf(x, [0],[1],[2],[3])", 0, 1200); + + m_kernel->SetParameter(0, m_digiCondTool->cb_alpha(ctx)); + m_kernel->SetParameter(1, m_digiCondTool->cb_n(ctx)); + m_kernel->SetParameter(2, m_digiCondTool->cb_sigma(ctx)); + m_kernel->SetParameter(3, m_digiCondTool->cb_mean(ctx)); + m_kernel->SetParameter(4, m_digiCondTool->cb_norm(ctx)); + + // Pre-evaluate time kernel for each bin + m_timekernel = m_digiTool->evaluate_timekernel(m_kernel); + + // Also save the baseline parameters + m_base_mean = m_digiCondTool->base_mean(ctx); + m_base_rms = m_digiCondTool->base_rms(ctx); + } // Create structure to store pulse for each channel std::map<Identifier, std::vector<uint16_t>> waveforms; diff --git a/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.h b/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.h index 52832562..99c374f5 100644 --- a/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.h +++ b/Scintillator/ScintDigiAlgs/src/ScintWaveformDigiAlg.h @@ -11,6 +11,7 @@ // Tool classes #include "WaveDigiTools/IWaveformDigitisationTool.h" #include "WaveformConditionsTools/IWaveformCableMappingTool.h" +#include "WaveformConditionsTools/IWaveformDigiConditionsTool.h" // Handles #include "StoreGate/ReadHandleKey.h" @@ -63,23 +64,15 @@ class ScintWaveformDigiAlg : public AthReentrantAlgorithm { /// - /** @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"}; - Gaudi::Property<double> m_CB_sigma {this, "CB_sigma", 0, "Sigma of the crystal ball function"}; - Gaudi::Property<double> m_CB_norm {this, "CB_norm", 0, "Norm of the crystal ball function"}; - - 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"}; - //@} + // We use these a lot, so read them once from the conditions tool + mutable float m_base_mean; + mutable float m_base_rms; /** Kernel PDF and evaluated values **/ //@{ - TF1* m_kernel; - std::vector<float> m_timekernel; + mutable TF1* m_kernel; + mutable std::vector<float> m_timekernel; //@} @@ -101,6 +94,12 @@ class ScintWaveformDigiAlg : public AthReentrantAlgorithm { ToolHandle<IWaveformCableMappingTool> m_mappingTool {this, "WaveformCableMappingTool", "WaveformCableMappingTool"}; + /** + * @name Digitization parameters tool + */ + ToolHandle<IWaveformDigiConditionsTool> m_digiCondTool + {this, "DigiConditionsTool", ""}; + /** * @name Input HITS using SG::ReadHandleKey */ diff --git a/Waveform/WaveformConditions/WaveCondUtils/scripts/makeDigiDB.py b/Waveform/WaveformConditions/WaveCondUtils/scripts/makeDigiDB.py new file mode 100755 index 00000000..202c5e26 --- /dev/null +++ b/Waveform/WaveformConditions/WaveCondUtils/scripts/makeDigiDB.py @@ -0,0 +1,156 @@ +#!/bin/env python +# +# Create digitization DB +# +# Can test results with +# AtlCoolConsole.py "sqlite://;schema=waveform_digi.db;dbname=OFLP200" +# +# Can merge with ALLP200.db with +# AtlCoolCopy "sqlite://;schema=waveform_digi.db;dbname=OFLP200" "sqlite://;schema=ALLP200.db;dbname=OFLP200" + +filename = "waveform_digi.db" + +import os +import sys +from PyCool import cool + +# Useful utilities for manipulating COOL files +# See https://gitlab.cern.ch/atlas/athena/-/blob/master/Database/CoolConvUtilities/python/AtlCoolLib.py +import CoolConvUtilities.AtlCoolLib as AtlCoolLib + +# Delete file if it exists +if os.path.exists(filename): + print(f"File {filename} exists, deleting...") + os.remove(filename) + +# Open new DB (forceOpen will create if it doesn't exist) +connect_string = f'sqlite://;schema={filename};dbname=OFLP200' +db = AtlCoolLib.forceOpen(connect_string) + +if not db: + print(f"Error opening {connect_string}") + sys.exit(1) + +# Description creates type of folder (run/lumi keyed, list of channels) +description = AtlCoolLib.athenaDesc(runLumi=True, datatype="CondAttrListCollection") + +# Define the folder payload +spec = cool.RecordSpecification() +spec.extend("base_mean", cool.StorageType.Float) +spec.extend("base_rms", cool.StorageType.Float) +spec.extend("cb_norm", cool.StorageType.Float) +spec.extend("cb_mean", cool.StorageType.Float) +spec.extend("cb_sigma", cool.StorageType.Float) +spec.extend("cb_alpha", cool.StorageType.Float) +spec.extend("cb_n", cool.StorageType.Float) + +# ensureFolder creates as needed +wave_folder = db.createFolderSet("/WAVE") +folder = AtlCoolLib.ensureFolder(db, '/WAVE/Digitization', spec, description, + version=cool.FolderVersioning.MULTI_VERSION) + +if not folder: + print("Could not access or create folders!") + print(e) + sys.exit(1) + +# Crystalball function Parameters estimated from Deion's slides uploaded at +# https://indico.cern.ch/event/1099652/contributions/4626975/attachments/2352595/4013927/Faser-Physics-run3933-plots.pdf (20/01/2022) + +# Fill values into record +# Values in ADC counts +base_mean = 15650. +base_rms = 3. + +# Calorimeter default (low gain/filters) +calo_record = cool.Record(spec) +calo_record['base_mean'] = base_mean +calo_record['base_rms'] = base_rms +calo_record['cb_norm'] = 0.56 +calo_record['cb_mean'] = 820 # Time in ns +calo_record['cb_sigma'] = 3.67 +calo_record['cb_alpha'] = -0.32 +calo_record['cb_n'] = 1000. + +vetonu_record = cool.Record(spec) +vetonu_record['base_mean'] = base_mean +vetonu_record['base_rms'] = base_rms +vetonu_record['cb_norm'] = 7040 +vetonu_record['cb_mean'] = 815 # Time in ns +vetonu_record['cb_sigma'] = 5.0 +vetonu_record['cb_alpha'] = -0.28 +vetonu_record['cb_n'] = 1000. + +veto_record = cool.Record(spec) +veto_record['base_mean'] = base_mean +veto_record['base_rms'] = base_rms +veto_record['cb_norm'] = 6840 +veto_record['cb_mean'] = 815 # Time in ns +veto_record['cb_sigma'] = 3.35 +veto_record['cb_alpha'] = -0.32 +veto_record['cb_n'] = 9. + +timing_record = cool.Record(spec) +timing_record['base_mean'] = base_mean +timing_record['base_rms'] = base_rms +timing_record['cb_norm'] = 4240 +timing_record['cb_mean'] = 815 # Time in ns +timing_record['cb_sigma'] = 3.21 +timing_record['cb_alpha'] = -0.424 +timing_record['cb_n'] = 6.14 + +preshower_record = cool.Record(spec) +preshower_record['base_mean'] = base_mean +preshower_record['base_rms'] = base_rms +preshower_record['cb_norm'] = 400 +preshower_record['cb_mean'] = 846 # Time in ns +preshower_record['cb_sigma'] = 4.0 +preshower_record['cb_alpha'] = -0.32 +preshower_record['cb_n'] = 1000. + +# Low gain, filters in default +tag = "WAVE-Digitization-01-LG" +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, calo_record, 0, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, vetonu_record, 1, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, veto_record, 2, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, timing_record, 3, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, preshower_record, 4, tag) +folder.createTagRelation("WAVE-01", tag) + +# Also associate this default with all of the global tags +# We will use a folder override to set other conditions +wave_folder.createTagRelation("OFLCOND-FASER-TB00", "WAVE-01") +wave_folder.createTagRelation("OFLCOND-FASER-01", "WAVE-01") +wave_folder.createTagRelation("OFLCOND-FASER-02", "WAVE-01") +wave_folder.createTagRelation("OFLCOND-FASER-03", "WAVE-01") + +# Low gain, filters out +tag = "WAVE-Digitization-01-LG-nofilt" +calo_record['cb_norm'] = 5.6 +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, calo_record, 0, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, vetonu_record, 1, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, veto_record, 2, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, timing_record, 3, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, preshower_record, 4, tag) + +# High gain +tag = "WAVE-Digitization-01-HG" +calo_record['cb_norm'] = 16.8 +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, calo_record, 0, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, vetonu_record, 1, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, veto_record, 2, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, timing_record, 3, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, preshower_record, 4, tag) + +# High gain, filters out +tag = "WAVE-Digitization-01-HG-nofilt" +calo_record['cb_norm'] = 168 +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, calo_record, 0, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, vetonu_record, 1, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, veto_record, 2, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, timing_record, 3, tag) +folder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, preshower_record, 4, tag) + +# All done +db.closeDatabase() +print('Database completed') diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/WaveformConditionsTools/IWaveformDigiConditionsTool.h b/Waveform/WaveformConditions/WaveformConditionsTools/WaveformConditionsTools/IWaveformDigiConditionsTool.h new file mode 100644 index 00000000..1bfaf0dd --- /dev/null +++ b/Waveform/WaveformConditions/WaveformConditionsTools/WaveformConditionsTools/IWaveformDigiConditionsTool.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS and FAsER collaborations +*/ + +/** @file IWaveformDigiTool.h Interface file for WaveformDigiTool. + * + * Provides times and offsets (in ns) for different channels in the + * waveform digitizer. This aligns the input signals for different + * path lengths and cable delays. + * + */ + +// Multiple inclusion protection +#ifndef IWAVEFORMDIGICONDITIONSTOOL +#define IWAVEFORMDIGICONDITIONSTOOL + +//STL includes +#include <map> + +//Gaudi Includes +#include "GaudiKernel/IAlgTool.h" +#include "GaudiKernel/EventContext.h" + + +class IWaveformDigiConditionsTool: virtual public IAlgTool { + + public: + + //----------Public Member Functions----------// + // Structors + virtual ~IWaveformDigiConditionsTool() = default; //!< Destructor + + /// Creates the InterfaceID and interfaceID() method + DeclareInterfaceID(IWaveformDigiConditionsTool, 1, 0); + + // Methods to return digitization parameters + + // Baseline parameters + virtual float base_mean(void) const = 0; + virtual float base_mean(const EventContext& ctx) const = 0; + + virtual float base_rms(void) const = 0; + virtual float base_rms(const EventContext& ctx) const = 0; + + // Crystal Ball parameters + virtual float cb_mean(void) const = 0; + virtual float cb_mean(const EventContext& ctx) const = 0; + + virtual float cb_sigma(void) const = 0; + virtual float cb_sigma(const EventContext& ctx) const = 0; + + virtual float cb_norm(void) const = 0; + virtual float cb_norm(const EventContext& ctx) const = 0; + + virtual float cb_alpha(void) const = 0; + virtual float cb_alpha(const EventContext& ctx) const = 0; + + virtual float cb_n(void) const = 0; + virtual float cb_n(const EventContext& ctx) const = 0; +}; + +//---------------------------------------------------------------------- +#endif // WAVEFORMDIGITOOL diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformDigitizationConfig.py b/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformDigitizationConfig.py new file mode 100644 index 00000000..7eb07444 --- /dev/null +++ b/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformDigitizationConfig.py @@ -0,0 +1,21 @@ +""" Define methods to configure WaveformCableMapping + +Copyright (C) 2022 CERN for the benefit of the FASER collaboration +""" +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +from IOVDbSvc.IOVDbSvcConfig import addFolders + +def WaveformDititizationCfg(flags, **kwargs): + """ Return configured ComponentAccumulator for Waveform Dititization + + """ + + acc = ComponentAccumulator() + # tool = kwargs.get("WaveformCableMappingTool", WaveformCableMappingTool(flags)) + # Probably need to figure this out! + dbInstance = kwargs.get("dbInstance", "TRIGGER_OFL") + dbFolder = kwargs.get("dbFolder", "/WAVE/Digitization") + acc.merge(addFolders(flags, dbFolder, dbInstance, className="CondAttrListCollection")) + return acc + diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformDigiConditionsTool.cxx b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformDigiConditionsTool.cxx new file mode 100644 index 00000000..4e2fedd9 --- /dev/null +++ b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformDigiConditionsTool.cxx @@ -0,0 +1,173 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS and FASER collaborations +*/ + +/** @file WaveformDigiConditionsTool.cxx Implementation file for WaveformDigiConditionsTool. + @author Eric Torrence (04/05/22) +*/ + +#include "WaveformDigiConditionsTool.h" + +//---------------------------------------------------------------------- +WaveformDigiConditionsTool::WaveformDigiConditionsTool (const std::string& type, const std::string& name, const IInterface* parent) : + base_class(type, name, parent) +{ +} + +//---------------------------------------------------------------------- +StatusCode +WaveformDigiConditionsTool::initialize() { + // Read Cond Handle Key + + ATH_MSG_DEBUG("WaveformDigiConditionsTool::initialize()"); + + ATH_CHECK(m_digiReadKey.initialize()); + + // Deal with COOL channel + if (m_detector == "Calo") { + m_cool_channel = COOL_Calo; + } + else if (m_detector == "VetoNu") { + m_cool_channel = COOL_VetoNu; + } + else if (m_detector == "Veto") { + m_cool_channel = COOL_Veto; + } + else if (m_detector == "Trigger") { + m_cool_channel = COOL_Timing; + } + else if (m_detector == "Timing") { + m_cool_channel = COOL_Timing; + } + else if (m_detector == "Preshower") { + m_cool_channel = COOL_Preshower; + } + else { + ATH_MSG_FATAL("Unknown detector: " << m_detector); + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + +//---------------------------------------------------------------------- +StatusCode +WaveformDigiConditionsTool::finalize() { + // Print where you are + return StatusCode::SUCCESS; +} + +//---------------------------------------------------------------------- +float +WaveformDigiConditionsTool::base_mean(const EventContext& ctx) const { + return get_value(ctx, "base_mean"); +} + +float +WaveformDigiConditionsTool::base_rms(const EventContext& ctx) const { + return get_value(ctx, "base_rms"); +} + +float +WaveformDigiConditionsTool::cb_mean(const EventContext& ctx) const { + return get_value(ctx, "cb_mean"); +} + +float +WaveformDigiConditionsTool::cb_sigma(const EventContext& ctx) const { + return get_value(ctx, "cb_sigma"); +} + +float +WaveformDigiConditionsTool::cb_norm(const EventContext& ctx) const { + return get_value(ctx, "cb_norm"); +} + +float +WaveformDigiConditionsTool::cb_alpha(const EventContext& ctx) const { + return get_value(ctx, "cb_alpha"); +} + +float +WaveformDigiConditionsTool::cb_n(const EventContext& ctx) const { + return get_value(ctx, "cb_n"); +} + +//---------------------------------------------------------------------- +float +WaveformDigiConditionsTool::base_mean(void) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return base_mean(ctx); +} + +float +WaveformDigiConditionsTool::base_rms(void) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return base_rms(ctx); +} + +float +WaveformDigiConditionsTool::cb_mean(void) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return cb_mean(ctx); +} + +float +WaveformDigiConditionsTool::cb_sigma(void) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return cb_sigma(ctx); +} + +float +WaveformDigiConditionsTool::cb_norm(void) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return cb_norm(ctx); +} + +float +WaveformDigiConditionsTool::cb_alpha(void) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return cb_alpha(ctx); +} + +float +WaveformDigiConditionsTool::cb_n(void) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return cb_n(ctx); +} + + +//---------------------------------------------------------------------- +float +WaveformDigiConditionsTool::get_value(const EventContext& ctx, std::string arg) const { + + float val = -1.; + + // Read Cond Handle + SG::ReadCondHandle<CondAttrListCollection> readHandle{m_digiReadKey, ctx}; + const CondAttrListCollection* readCdo{*readHandle}; + if (readCdo==nullptr) { + ATH_MSG_FATAL("Null pointer to the read conditions object"); + return val; + } + + // Read value for specific channel + const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(m_cool_channel)}; + + if (payload.exists(arg) and not payload[arg].isNull()) { + val = payload[arg].data<float>(); + ATH_MSG_DEBUG("Found digi COOL channel " << m_cool_channel << " " << arg << " as " << val); + } else { + ATH_MSG_WARNING("No valid " << arg << " value found for digi COOL channel "<< m_cool_channel<<"!"); + } + + return val; + +} + + + + + + + diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformDigiConditionsTool.h b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformDigiConditionsTool.h new file mode 100644 index 00000000..e5e82320 --- /dev/null +++ b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformDigiConditionsTool.h @@ -0,0 +1,95 @@ +// -*- C++ -*- + +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS and CERN collaborations +*/ + +/** @file WaveformDigiConditionsTool.h Header file for WaveformDigiConditionsTool. + @author Eric Torrence, 20/04/22 +*/ + +// Multiple inclusion protection +#ifndef WAVEFORM_DIGI_CONDITIONS_TOOL +#define WAVEFORM_DIGI_CONDITIONS_TOOL + +// Include interface class +#include "AthenaBaseComps/AthAlgTool.h" +#include "WaveformConditionsTools/IWaveformDigiConditionsTool.h" + +// Include Athena stuff +#include "AthenaPoolUtilities/CondAttrListCollection.h" +#include "StoreGate/ReadCondHandleKey.h" + +#include "GaudiKernel/ICondSvc.h" +#include "Gaudi/Property.h" + +// Include Gaudi classes +#include "GaudiKernel/EventContext.h" + +/** This class contains a Tool that reads Waveform digi data and makes it available + to other algorithms. +*/ + +class WaveformDigiConditionsTool: public extends<AthAlgTool, IWaveformDigiConditionsTool> { + + public: + //----------Public Member Functions----------// + // Structors + WaveformDigiConditionsTool(const std::string& type, const std::string& name, const IInterface* parent); //!< Constructor + virtual ~WaveformDigiConditionsTool() = default; //!< Destructor + + // Standard Gaudi functions + virtual StatusCode initialize() override; //!< Gaudi initialiser + virtual StatusCode finalize() override; //!< Gaudi finaliser + + // Methods to return digigitization data + + // Baseline parameters + virtual float base_mean(void) const override; + virtual float base_mean(const EventContext& ctx) const override; + + virtual float base_rms(void) const override; + virtual float base_rms(const EventContext& ctx) const override; + + // Crystal ball parameters + virtual float cb_mean(void) const override; + virtual float cb_mean(const EventContext& ctx) const override; + + virtual float cb_sigma(void) const override; + virtual float cb_sigma(const EventContext& ctx) const override; + + virtual float cb_norm(void) const override; + virtual float cb_norm(const EventContext& ctx) const override; + + virtual float cb_alpha(void) const override; + virtual float cb_alpha(const EventContext& ctx) const override; + + virtual float cb_n(void) const override; + virtual float cb_n(const EventContext& ctx) const override; + + + private: + + // COOL channel specifier (Calo, VetoNu, Veto, Trigger or Timing, Preshower) + Gaudi::Property<std::string> m_detector{this, "Detector", "", "Detector type"}; + + // Read Cond Handle + SG::ReadCondHandleKey<CondAttrListCollection> m_digiReadKey{this, "DigiReadKey", "/WAVE/Digitization", "Key of digi conditions folder"}; + + // COOL channel specifier in channel id + int m_cool_channel; + + float get_value(const EventContext& ctx, std::string argument) const; + + enum COOL_Channel { + COOL_Calo, + COOL_VetoNu, + COOL_Veto, + COOL_Timing, + COOL_Preshower + }; + +}; + +//---------------------------------------------------------------------- +#endif // WAVEFORM_DIGI_CONDITIONS_TOOL diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformTimingTool.h b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformTimingTool.h index b69e52b2..63a5b2b6 100644 --- a/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformTimingTool.h +++ b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformTimingTool.h @@ -61,7 +61,7 @@ class WaveformTimingTool: public extends<AthAlgTool, IWaveformTimingTool> { SG::ReadCondHandleKey<AthenaAttributeList> m_timingReadKey{this, "TimingReadKey", "/WAVE/DAQ/Timing", "Key of timing folder"}; SG::ReadCondHandleKey<CondAttrListCollection> m_offsetReadKey{this, "OffsetReadKey", "/WAVE/DAQ/TimingOffset", "Key of timing offset folder"}; - ServiceHandle<ICondSvc> m_condSvc{this, "CondSvc", "CondSvc"}; + //ServiceHandle<ICondSvc> m_condSvc{this, "CondSvc", "CondSvc"}; }; diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/src/components/WaveformConditionsTools_entries.cxx b/Waveform/WaveformConditions/WaveformConditionsTools/src/components/WaveformConditionsTools_entries.cxx index f694fef6..a37ff174 100644 --- a/Waveform/WaveformConditions/WaveformConditionsTools/src/components/WaveformConditionsTools_entries.cxx +++ b/Waveform/WaveformConditions/WaveformConditionsTools/src/components/WaveformConditionsTools_entries.cxx @@ -1,7 +1,9 @@ #include "../WaveformRangeTool.h" #include "../WaveformTimingTool.h" #include "../WaveformCableMappingTool.h" +#include "../WaveformDigiConditionsTool.h" DECLARE_COMPONENT( WaveformRangeTool ) DECLARE_COMPONENT( WaveformTimingTool ) DECLARE_COMPONENT( WaveformCableMappingTool ) +DECLARE_COMPONENT( WaveformDigiConditionsTool ) -- GitLab