From 72127bad535e21f576aeedf5363791c5b326854e Mon Sep 17 00:00:00 2001
From: Deion Elgin Fellers <dfellers@lxplus724.cern.ch>
Date: Fri, 30 Sep 2022 09:49:20 +0200
Subject: [PATCH 1/4] first pass at adding energy calibration code which
 accesses calibration variables from a COOL db

---
 Calorimeter/CaloRecAlgs/CMakeLists.txt        |   2 +-
 .../CaloRecAlgs/python/CaloRecAlgsConfig.py   |   7 +
 Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx    | 152 +++++++++++++++++-
 Calorimeter/CaloRecAlgs/src/CaloRecAlg.h      |  22 +++
 Calorimeter/CaloRecTools/CMakeLists.txt       |  27 ++++
 .../CaloRecTools/ICaloReconstructionTool.h    |  31 ++++
 .../src/CaloReconstructionTool.cxx            |  38 +++++
 .../CaloRecTools/src/CaloReconstructionTool.h |  38 +++++
 .../src/components/CaloRecTools_entries.cxx   |   3 +
 .../Reconstruction/scripts/faser_reco.py      |   8 +-
 10 files changed, 322 insertions(+), 6 deletions(-)
 create mode 100644 Calorimeter/CaloRecTools/CMakeLists.txt
 create mode 100644 Calorimeter/CaloRecTools/CaloRecTools/ICaloReconstructionTool.h
 create mode 100644 Calorimeter/CaloRecTools/src/CaloReconstructionTool.cxx
 create mode 100644 Calorimeter/CaloRecTools/src/CaloReconstructionTool.h
 create mode 100644 Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx

diff --git a/Calorimeter/CaloRecAlgs/CMakeLists.txt b/Calorimeter/CaloRecAlgs/CMakeLists.txt
index 219db92a3..87ae6a06d 100644
--- a/Calorimeter/CaloRecAlgs/CMakeLists.txt
+++ b/Calorimeter/CaloRecAlgs/CMakeLists.txt
@@ -9,7 +9,7 @@ atlas_subdir( CaloRecAlgs )
 atlas_add_component( CaloRecAlgs
                      src/*.cxx src/*.h
                      src/components/*.cxx
-                     LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserCalorimeter xAODFaserWaveform)
+                     LINK_LIBRARIES AthenaKernel GaudiKernel AthenaBaseComps AthenaPoolUtilities StoreGateLib xAODFaserCalorimeter xAODFaserWaveform)
 
 atlas_install_python_modules( python/*.py )
 
diff --git a/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py b/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py
index 034bf08b5..ea3759ab2 100644
--- a/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py
+++ b/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py
@@ -4,6 +4,7 @@ Copyright (C) 2020 CERN for the benefit of the FASER collaboration
 """
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from AthenaConfiguration.ComponentFactory import CompFactory
+from IOVDbSvc.IOVDbSvcConfig import addFolders
 
 from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
 
@@ -25,6 +26,12 @@ def CalorimeterReconstructionCfg(flags, **kwargs):
     #recoAlg.CalorimeterReconstructionTool = tool
     acc.addEventAlgo(recoAlg)
 
+    dbInstance = kwargs.get("dbInstance", "TRIGGER_OFL") # what should this be set to???
+
+    acc.merge(addFolders(flags, "/WAVE/Calibration/HV", dbInstance, className="CondAttrListCollection"))
+    acc.merge(addFolders(flags, "/WAVE/Calibration/HV_ref", dbInstance, className="CondAttrListCollection"))
+    acc.merge(addFolders(flags, "/WAVE/Calibration/MIP_charge_ref", dbInstance, className="CondAttrListCollection"))
+
     return acc
 
 def CalorimeterReconstructionOutputCfg(flags, **kwargs):
diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
index 4b4d6f158..493fe87d3 100644
--- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
+++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
@@ -22,6 +22,11 @@ CaloRecAlg::initialize() {
   // Set key to write container
   ATH_CHECK( m_caloHitContainerKey.initialize() );
 
+  // Set key to read calibratiion variables from data base
+  ATH_CHECK( m_PMT_HV_ReadKey.initialize() );
+  ATH_CHECK( m_PMT_HV_ref_ReadKey.initialize() );
+  ATH_CHECK( m_MIPcharge_ref_ReadKey.initialize() );
+
   return StatusCode::SUCCESS;
 }
 
@@ -68,6 +73,8 @@ CaloRecAlg::execute(const EventContext& ctx) const {
   // Reconstruct all waveforms
   //CHECK( m_recoTool->reconstructAll(*waveformHandle, clockptr, hitContainerHandle.ptr()) );
 
+  ATH_MSG_DEBUG("DEION test" );
+
   // Find peak time (most significant hit)
   const xAOD::WaveformHit* peakHit = findPeakHit(*caloWaveHitHandle);
   if (peakHit == NULL) return StatusCode::SUCCESS;
@@ -76,7 +83,16 @@ CaloRecAlg::execute(const EventContext& ctx) const {
   xAOD::CalorimeterHit* calo_hit = new xAOD::CalorimeterHit();
   caloHitContainerHandle->push_back(calo_hit);
 
-  calo_hit->set_raw_energy(-1.);  // Dummy value
+  calo_hit->set_raw_energy(peakHit->raw_integral()/50.0);  // Dummy value
+  ATH_MSG_DEBUG("DEION, calo_hit filled with integral of  '" << peakHit->raw_integral()/50.0 );
+
+  float PMT_hv = getHV(peakHit->channel());
+  float PMT_hv_ref = getHV_ref(peakHit->channel());
+  float MIPcharge_ref = getMIPcharge_ref(peakHit->channel());
+
+  ATH_MSG_DEBUG("DEION, calo_hit has HV of '" << PMT_hv );
+  ATH_MSG_DEBUG("DEION, calo_hit has HV_ref of '" << PMT_hv_ref );
+  ATH_MSG_DEBUG("DEION, calo_hit has MIP_charge_ref of '" << MIPcharge_ref );
 
   // Find closest hits in time per channel
   std::map<int, const xAOD::WaveformHit*> hitMap;
@@ -121,3 +137,137 @@ CaloRecAlg::findPeakHit(const xAOD::WaveformHitContainer& hitContainer) const {
   if (peakHit->status_bit(xAOD::WaveformStatus::THRESHOLD_FAILED)) return NULL;
   return peakHit;
 }
+
+//----------------------------------------------------------------------
+float CaloRecAlg::getHV(const EventContext& ctx, int channel) const {
+
+  ATH_MSG_DEBUG("in getHV("<<channel<<")");
+
+  float HV=0.;
+
+  // Read Cond Handle
+  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_PMT_HV_ReadKey, ctx};
+  const CondAttrListCollection* readCdo{*readHandle}; 
+  if (readCdo==nullptr) {
+    ATH_MSG_FATAL("Null pointer to the read conditions object");
+    return HV;
+  }
+  // Get the validitiy range
+  EventIDRange rangeW;
+  if (not readHandle.range(rangeW)) {
+    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
+    return HV;
+  }
+  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
+  ATH_MSG_DEBUG("Range of input is " << rangeW);
+
+  // Read offset for specific channel
+  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
+
+  if (payload.exists("HV") and not payload["HV"].isNull()) {
+    HV = payload["HV"].data<float>();
+    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", HV as " << HV);
+  } else {
+    ATH_MSG_WARNING("No valid HV found for channel "<<channel<<"!");
+  }
+
+  return HV;
+
+}
+
+float CaloRecAlg::getHV(int channel) const {
+  const EventContext& ctx(Gaudi::Hive::currentContext());
+  return CaloRecAlg::getHV(ctx, channel);
+}
+
+//----------------------------------------------------------------------
+float CaloRecAlg::getHV_ref(const EventContext& ctx, int channel) const {
+
+  ATH_MSG_DEBUG("in getHV_ref("<<channel<<")");
+
+  float HV_ref=0.;
+
+  // Read Cond Handle
+  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_PMT_HV_ref_ReadKey, ctx};
+  const CondAttrListCollection* readCdo{*readHandle};
+  if (readCdo==nullptr) {
+    ATH_MSG_FATAL("Null pointer to the read conditions object");
+    return HV_ref;
+  }
+  // Get the validitiy range
+  EventIDRange rangeW;
+  if (not readHandle.range(rangeW)) {
+    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
+    return HV_ref;
+  }
+  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
+  ATH_MSG_DEBUG("Range of input is " << rangeW);
+
+  // Read offset for specific channel
+  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
+
+  if (payload.exists("HV_ref") and not payload["HV_ref"].isNull()) {
+    HV_ref = payload["HV_ref"].data<float>();
+    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", HV_ref as " << HV_ref);
+  } else {
+    ATH_MSG_WARNING("No valid HV_ref found for channel "<<channel<<"!");
+  }
+
+  return HV_ref;
+
+}
+
+float CaloRecAlg::getHV_ref(int channel) const {
+  const EventContext& ctx(Gaudi::Hive::currentContext());
+  return CaloRecAlg::getHV_ref(ctx, channel);
+}
+
+//----------------------------------------------------------------------
+float CaloRecAlg::getMIPcharge_ref(const EventContext& ctx, int channel) const {
+
+  ATH_MSG_DEBUG("in getMIPcharge_ref("<<channel<<")");
+
+  float MIP_charge_ref =0.;
+
+  // Read Cond Handle
+  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_MIPcharge_ref_ReadKey, ctx};
+  const CondAttrListCollection* readCdo{*readHandle};
+  if (readCdo==nullptr) {
+    ATH_MSG_FATAL("Null pointer to the read conditions object");
+    return MIP_charge_ref;
+  }
+  // Get the validitiy range
+  EventIDRange rangeW;
+  if (not readHandle.range(rangeW)) {
+    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
+    return MIP_charge_ref;
+  }
+  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
+  ATH_MSG_DEBUG("Range of input is " << rangeW);
+
+  // Read offset for specific channel
+  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
+
+  if (payload.exists("MIP_charge_ref") and not payload["MIP_charge_ref"].isNull()) {
+    MIP_charge_ref = payload["MIP_charge_ref"].data<float>();
+    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", MIP_charge_ref as " << MIP_charge_ref);
+  } else {
+    ATH_MSG_WARNING("No valid MIP_charge_ref found for channel "<<channel<<"!");
+  }
+
+  return MIP_charge_ref;
+
+}
+
+float CaloRecAlg::getMIPcharge_ref(int channel) const {
+  const EventContext& ctx(Gaudi::Hive::currentContext());
+  return CaloRecAlg::getMIPcharge_ref(ctx, channel);
+}
+
+
+
+
+//----------------------------------------------------------------------
+
+
+
diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
index bd98e9afd..f68c84ed8 100644
--- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
+++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
@@ -14,6 +14,10 @@
 // Tool classes
 //#include "CaloRecTools/ICalorimeterReconstructionTool.h"
 
+// Include Athena stuff for Conditions db reading
+#include "AthenaPoolUtilities/CondAttrListCollection.h"
+#include "StoreGate/ReadCondHandleKey.h"
+
 // Handles
 #include "StoreGate/ReadHandleKey.h"
 #include "StoreGate/WriteHandleKey.h"
@@ -21,6 +25,10 @@
 // Gaudi
 #include "GaudiKernel/ServiceHandle.h"
 #include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/EventContext.h"
+#include "GaudiKernel/ICondSvc.h"
+#include "Gaudi/Property.h"
+
 
 // STL
 #include <string>
@@ -78,6 +86,20 @@ class CaloRecAlg : public AthReentrantAlgorithm {
   const xAOD::WaveformHit* 
     findPeakHit(const xAOD::WaveformHitContainer& hitContainer) const;
 
+  virtual float getHV(const EventContext& ctx, int channel) const;
+  virtual float getHV(int channel) const;
+
+  virtual float getHV_ref(const EventContext& ctx, int channel) const;
+  virtual float getHV_ref(int channel) const;
+
+  virtual float getMIPcharge_ref(const EventContext& ctx, int channel) const;
+  virtual float getMIPcharge_ref(int channel) const;
+
+  // Read Cond Handle
+  SG::ReadCondHandleKey<CondAttrListCollection> m_PMT_HV_ReadKey{this, "PMT_HV_ReadKey", "/WAVE/Calibration/HV", "Key of folder for PMT HV reading"};
+  SG::ReadCondHandleKey<CondAttrListCollection> m_PMT_HV_ref_ReadKey{this, "PMT_HV_ref_ReadKey", "/WAVE/Calibration/HV_ref", "Key of folder for PMT HV at time of MIP calibration measurement"};
+  SG::ReadCondHandleKey<CondAttrListCollection> m_MIPcharge_ref_ReadKey{this, "MIPcharge_ref_ReadKey", "/WAVE/Calibration/MIP_charge_ref", "Key of folder for MIPcharge calibration measurment"};
+
 };
 
 #endif // CALORECALGS_CALORECALG_H
diff --git a/Calorimeter/CaloRecTools/CMakeLists.txt b/Calorimeter/CaloRecTools/CMakeLists.txt
new file mode 100644
index 000000000..36c9f1dcd
--- /dev/null
+++ b/Calorimeter/CaloRecTools/CMakeLists.txt
@@ -0,0 +1,27 @@
+################################################################################
+# Package: WaveRecTools
+################################################################################
+
+# Declare the package name:
+atlas_subdir( CaloRecTools )
+
+# External dependencies:
+find_package( ROOT )
+
+# Component(s) in the package:
+atlas_add_library( CaloRecToolsLib
+                   CaloRecTools/*.h src/*.cxx src/*.h
+                   PUBLIC_HEADERS CaloRecTools
+                   PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                   LINK_LIBRARIES AthenaBaseComps AthenaKernel GeoPrimitives Identifier
+                   PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES}
+		   )
+
+atlas_add_component( CaloRecTools
+		     src/components/*.cxx 
+		     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} 
+		     AthenaBaseComps GaudiKernel 
+		     CaloRecToolsLib)
+
+
diff --git a/Calorimeter/CaloRecTools/CaloRecTools/ICaloReconstructionTool.h b/Calorimeter/CaloRecTools/CaloRecTools/ICaloReconstructionTool.h
new file mode 100644
index 000000000..d6decfbd0
--- /dev/null
+++ b/Calorimeter/CaloRecTools/CaloRecTools/ICaloReconstructionTool.h
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/**
+ * @file ICaloReconstructionTool.h
+ * Header file for the ICaloReconstructionTool class
+ * @author Eric Torrence, 2021
+ */
+
+
+#ifndef CALORECTOOLS_ICALOCONSTRUCTIONTOOL_H
+#define CALORECTOOLS_ICALOCONSTRUCTIONTOOL_H
+
+// Base class
+#include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+
+///Interface for Calo reco algorithms
+class ICaloReconstructionTool : virtual public IAlgTool 
+{
+  public:
+
+  // InterfaceID
+  DeclareInterfaceID(ICaloReconstructionTool, 1, 0);
+
+  virtual ~ICaloReconstructionTool() = default;
+
+};
+
+#endif // SCINTRECTOOLS_IWAVEFORMRECONSTRUCTIONTOOL_H
diff --git a/Calorimeter/CaloRecTools/src/CaloReconstructionTool.cxx b/Calorimeter/CaloRecTools/src/CaloReconstructionTool.cxx
new file mode 100644
index 000000000..438dd77f3
--- /dev/null
+++ b/Calorimeter/CaloRecTools/src/CaloReconstructionTool.cxx
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/**
+ * @file CaloReconstructionTool.cxx
+ * Implementation file for the CaloReconstructionTool.cxx
+ * @ author E. Torrence, 2021
+ **/
+
+#include "CaloReconstructionTool.h"
+
+#include "TH1F.h"
+#include "TF1.h"
+#include "TFitResult.h"
+#include "TFitResultPtr.h"
+#include "TGraph.h"
+#include "TError.h"
+
+#include <vector>
+#include <tuple>
+#include <math.h>
+
+// Constructor
+CaloReconstructionTool::CaloReconstructionTool(const std::string& type, const std::string& name, const IInterface* parent) :
+  base_class(type, name, parent)
+{
+}
+
+// Initialization
+StatusCode
+CaloReconstructionTool::initialize() {
+  ATH_MSG_INFO( name() << "::initalize()" );
+
+  return StatusCode::SUCCESS;
+}
+
+
diff --git a/Calorimeter/CaloRecTools/src/CaloReconstructionTool.h b/Calorimeter/CaloRecTools/src/CaloReconstructionTool.h
new file mode 100644
index 000000000..55ea137ef
--- /dev/null
+++ b/Calorimeter/CaloRecTools/src/CaloReconstructionTool.h
@@ -0,0 +1,38 @@
+/*
+   Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/** @file CaloReconstructionTool.h
+ *  Header file for CaloReconstructionTool.h
+ *
+ */
+#ifndef CALORECTOOLS_CALORECONSTRUCTIONTOOL_H
+#define CALORECTOOLS_CALORECONSTRUCTIONTOOL_H
+
+//Athena
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "CaloRecTools/ICaloReconstructionTool.h"
+
+//Gaudi
+#include "GaudiKernel/ToolHandle.h"
+
+//STL
+#include <string>
+#include <vector>
+
+class CaloReconstructionTool: public extends<AthAlgTool, ICaloReconstructionTool> {
+ public:
+
+  /// Normal constructor for an AlgTool; 'properties' are also declared here
+  CaloReconstructionTool(const std::string& type, 
+			     const std::string& name, const IInterface* parent);
+
+  /// Retrieve the necessary services in initialize
+  StatusCode initialize();
+
+ private:
+
+
+};
+
+#endif // CALORECTOOLS_CALOCONSTRUCTIONTOOL_H
diff --git a/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx b/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx
new file mode 100644
index 000000000..183a4878b
--- /dev/null
+++ b/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx
@@ -0,0 +1,3 @@
+#include "../CaloReconstructionTool.h"
+
+DECLARE_COMPONENT( CaloReconstructionTool )
diff --git a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
index 4e233bf4f..8ebbc421c 100755
--- a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
+++ b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
@@ -181,8 +181,8 @@ from WaveRecAlgs.WaveRecAlgsConfig import WaveformReconstructionCfg
 acc.merge(WaveformReconstructionCfg(ConfigFlags))
 
 # Not ready for primetime
-# from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionCfg
-# acc.merge(CalorimeterReconstructionCfg(ConfigFlags))
+from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionCfg
+acc.merge(CalorimeterReconstructionCfg(ConfigFlags))
 
 # Tracker clusters
 from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg
@@ -252,8 +252,8 @@ from WaveRecAlgs.WaveRecAlgsConfig import WaveformReconstructionOutputCfg
 acc.merge(WaveformReconstructionOutputCfg(ConfigFlags))
 
 # Calorimeter reconstruction output
-# from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionOutputCfg
-# acc.merge(CalorimeterReconstructionOutputCfg(ConfigFlags))
+from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionOutputCfg
+acc.merge(CalorimeterReconstructionOutputCfg(ConfigFlags))
 
 # Check what we have
 print( "Writing out xAOD objects:" )
-- 
GitLab


From 38734c8bbf318e8f02ac33e7aea44b1d52f5219c Mon Sep 17 00:00:00 2001
From: Deion Elgin Fellers <dfellers@lxplus727.cern.ch>
Date: Thu, 3 Nov 2022 15:02:13 +0100
Subject: [PATCH 2/4] add calorimeter calibration package

---
 Calorimeter/CaloRecAlgs/CMakeLists.txt        |   2 +-
 .../CaloRecAlgs/python/CaloRecAlgsConfig.py   |  16 +-
 Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx    | 249 +++++-------------
 Calorimeter/CaloRecAlgs/src/CaloRecAlg.h      |  36 +--
 Calorimeter/CaloRecTools/CMakeLists.txt       |  11 +-
 .../CaloRecTools/CaloRecTools/ICaloRecTool.h  |  45 ++++
 .../CaloRecTools/ICaloReconstructionTool.h    |  31 ---
 .../CaloRecTools/python/CaloRecToolConfig.py  |  28 ++
 Calorimeter/CaloRecTools/src/CaloRecTool.cxx  | 195 ++++++++++++++
 Calorimeter/CaloRecTools/src/CaloRecTool.h    |  83 ++++++
 .../src/CaloReconstructionTool.cxx            |  38 ---
 .../CaloRecTools/src/CaloReconstructionTool.h |  38 ---
 .../src/components/CaloRecTools_entries.cxx   |   4 +-
 .../Root/CalorimeterHitAuxContainer_v1.cxx    |   8 +-
 .../Root/CalorimeterHit_v1.cxx                |  32 +--
 .../versions/CalorimeterHitAuxContainer_v1.h  |  11 +-
 .../versions/CalorimeterHit_v1.h              |  24 +-
 17 files changed, 487 insertions(+), 364 deletions(-)
 create mode 100644 Calorimeter/CaloRecTools/CaloRecTools/ICaloRecTool.h
 delete mode 100644 Calorimeter/CaloRecTools/CaloRecTools/ICaloReconstructionTool.h
 create mode 100644 Calorimeter/CaloRecTools/python/CaloRecToolConfig.py
 create mode 100644 Calorimeter/CaloRecTools/src/CaloRecTool.cxx
 create mode 100644 Calorimeter/CaloRecTools/src/CaloRecTool.h
 delete mode 100644 Calorimeter/CaloRecTools/src/CaloReconstructionTool.cxx
 delete mode 100644 Calorimeter/CaloRecTools/src/CaloReconstructionTool.h

diff --git a/Calorimeter/CaloRecAlgs/CMakeLists.txt b/Calorimeter/CaloRecAlgs/CMakeLists.txt
index 87ae6a06d..75d9d09a2 100644
--- a/Calorimeter/CaloRecAlgs/CMakeLists.txt
+++ b/Calorimeter/CaloRecAlgs/CMakeLists.txt
@@ -9,7 +9,7 @@ atlas_subdir( CaloRecAlgs )
 atlas_add_component( CaloRecAlgs
                      src/*.cxx src/*.h
                      src/components/*.cxx
-                     LINK_LIBRARIES AthenaKernel GaudiKernel AthenaBaseComps AthenaPoolUtilities StoreGateLib xAODFaserCalorimeter xAODFaserWaveform)
+                     LINK_LIBRARIES AthenaKernel GaudiKernel AthenaBaseComps AthenaPoolUtilities StoreGateLib xAODFaserCalorimeter xAODFaserWaveform CaloRecToolsLib)
 
 atlas_install_python_modules( python/*.py )
 
diff --git a/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py b/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py
index ea3759ab2..83839b9cb 100644
--- a/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py
+++ b/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py
@@ -1,36 +1,30 @@
-""" Define methods used to instantiate configured Waveform reconstruction tools and algorithms
+""" Define methods used to instantiate configured Calorimeter Calibration reconstruction tools and algorithms
 
-Copyright (C) 2020 CERN for the benefit of the FASER collaboration
+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
-
 from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
 
-#CalorimeterReconstructionTool = CompFactory.CalorimeterReconstructionTool
+from CaloRecTools.CaloRecToolConfig import CaloRecToolCfg
 
 # One stop shopping for normal FASER data
 def CalorimeterReconstructionCfg(flags, **kwargs):
     """ Return all algorithms and tools for Waveform reconstruction """
     acc = ComponentAccumulator()
 
-    #tool = CalorimeterReconstructionTool(name="CaloRecTool", **kwargs)
-
     kwargs.setdefault("CaloWaveHitContainerKey", "CaloWaveformHits")
     kwargs.setdefault("PreshowerWaveHitContainerKey", "PreshowerWaveformHits")
     kwargs.setdefault("CaloHitContainerKey", "CaloHits")
-    #kwargs.setdefault("CalorimeterReconstructionTool", tool)
+    kwargs.setdefault("PreshowerHitContainerKey", "PreshowerHits")
 
     recoAlg = CompFactory.CaloRecAlg("CaloRecAlg", **kwargs)
-    #recoAlg.CalorimeterReconstructionTool = tool
     acc.addEventAlgo(recoAlg)
 
     dbInstance = kwargs.get("dbInstance", "TRIGGER_OFL") # what should this be set to???
 
-    acc.merge(addFolders(flags, "/WAVE/Calibration/HV", dbInstance, className="CondAttrListCollection"))
-    acc.merge(addFolders(flags, "/WAVE/Calibration/HV_ref", dbInstance, className="CondAttrListCollection"))
-    acc.merge(addFolders(flags, "/WAVE/Calibration/MIP_charge_ref", dbInstance, className="CondAttrListCollection"))
+    acc.merge(CaloRecToolCfg(flags))
 
     return acc
 
diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
index 493fe87d3..f70993055 100644
--- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
+++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
@@ -1,4 +1,5 @@
 #include "CaloRecAlg.h"
+#include <math.h>
 
 CaloRecAlg::CaloRecAlg(const std::string& name, 
 		       ISvcLocator* pSvcLocator)
@@ -6,13 +7,9 @@ CaloRecAlg::CaloRecAlg(const std::string& name,
 
 }
 
-StatusCode 
-CaloRecAlg::initialize() {
+StatusCode CaloRecAlg::initialize() {
   ATH_MSG_INFO(name() << "::initalize()" );
 
-  // Initalize tools
-  //ATH_CHECK( m_recoTool.retrieve() );
-
   // Set key to read calo hits from
   ATH_CHECK( m_caloWaveHitContainerKey.initialize() );
 
@@ -21,24 +18,21 @@ CaloRecAlg::initialize() {
 
   // Set key to write container
   ATH_CHECK( m_caloHitContainerKey.initialize() );
+  ATH_CHECK( m_preshowerHitContainerKey.initialize() );
 
-  // Set key to read calibratiion variables from data base
-  ATH_CHECK( m_PMT_HV_ReadKey.initialize() );
-  ATH_CHECK( m_PMT_HV_ref_ReadKey.initialize() );
-  ATH_CHECK( m_MIPcharge_ref_ReadKey.initialize() );
+  // Initalize tools
+  ATH_CHECK( m_recoCalibTool.retrieve() );
 
   return StatusCode::SUCCESS;
 }
-
-StatusCode 
-CaloRecAlg::finalize() {
+//----------------------------------------------------------------------
+StatusCode CaloRecAlg::finalize() {
   ATH_MSG_INFO(name() << "::finalize()");
 
   return StatusCode::SUCCESS;
 }
-
-StatusCode 
-CaloRecAlg::execute(const EventContext& ctx) const {
+//----------------------------------------------------------------------
+StatusCode CaloRecAlg::execute(const EventContext& ctx) const {
   ATH_MSG_DEBUG("Executing");
 
   ATH_MSG_DEBUG("Run: " << ctx.eventID().run_number() 
@@ -68,206 +62,105 @@ CaloRecAlg::execute(const EventContext& ctx) const {
   ATH_CHECK( caloHitContainerHandle.record( std::make_unique<xAOD::CalorimeterHitContainer>(),
 					std::make_unique<xAOD::CalorimeterHitAuxContainer>() ) );
 
+  SG::WriteHandle<xAOD::CalorimeterHitContainer> preshowerHitContainerHandle(m_preshowerHitContainerKey, ctx);
+  ATH_CHECK( preshowerHitContainerHandle.record( std::make_unique<xAOD::CalorimeterHitContainer>(),
+                    std::make_unique<xAOD::CalorimeterHitAuxContainer>() ) );
+
   ATH_MSG_DEBUG("WaveformsHitContainer '" << caloHitContainerHandle.name() << "' initialized");
+  ATH_MSG_DEBUG("WaveformsHitContainer '" << preshowerHitContainerHandle.name() << "' initialized");
 
   // Reconstruct all waveforms
   //CHECK( m_recoTool->reconstructAll(*waveformHandle, clockptr, hitContainerHandle.ptr()) );
 
   ATH_MSG_DEBUG("DEION test" );
 
-  // Find peak time (most significant hit)
-  const xAOD::WaveformHit* peakHit = findPeakHit(*caloWaveHitHandle);
-  if (peakHit == NULL) return StatusCode::SUCCESS;
-
-  // Create a new calo hit
-  xAOD::CalorimeterHit* calo_hit = new xAOD::CalorimeterHit();
-  caloHitContainerHandle->push_back(calo_hit);
-
-  calo_hit->set_raw_energy(peakHit->raw_integral()/50.0);  // Dummy value
-  ATH_MSG_DEBUG("DEION, calo_hit filled with integral of  '" << peakHit->raw_integral()/50.0 );
-
-  float PMT_hv = getHV(peakHit->channel());
-  float PMT_hv_ref = getHV_ref(peakHit->channel());
-  float MIPcharge_ref = getMIPcharge_ref(peakHit->channel());
-
-  ATH_MSG_DEBUG("DEION, calo_hit has HV of '" << PMT_hv );
-  ATH_MSG_DEBUG("DEION, calo_hit has HV_ref of '" << PMT_hv_ref );
-  ATH_MSG_DEBUG("DEION, calo_hit has MIP_charge_ref of '" << MIPcharge_ref );
-
-  // Find closest hits in time per channel
-  std::map<int, const xAOD::WaveformHit*> hitMap;
-  for ( const auto& hit : *caloWaveHitHandle ) {
-    int channel = hit->channel();
-    if (hitMap.count(channel) == 0)
-      hitMap[channel] = hit;
-    else {
-      if (abs(hitMap[channel]->localtime() - peakHit->localtime()) > 
-	  abs(hit->localtime() - peakHit->localtime()))
-	hitMap[channel] = hit;
-    }
-  }
+  for( const auto& hit : *caloWaveHitHandle ) {
+    if (hit->status_bit(xAOD::WaveformStatus::SECONDARY)) continue;
 
-  // For each hit found, insert these into the caloHit
-  // Clear before association
-  calo_hit->clearCaloWaveformLinks();
-  for ( const auto& [chan, hit] : hitMap ) {
-    ATH_MSG_VERBOSE("Found hit " << *hit);
-    calo_hit->addCaloHit(caloWaveHitHandle.get(), hit);
-  }
+    // Create a new calo hit
+    xAOD::CalorimeterHit* calo_hit = new xAOD::CalorimeterHit();
+    caloHitContainerHandle->push_back(calo_hit);
 
-  ATH_MSG_DEBUG("CaloHitContainer '" << caloHitContainerHandle.name() << "' filled with "<< caloHitContainerHandle->size() <<" items");
+    ATH_MSG_DEBUG("calo_hit in channel " << hit->channel() );
 
-  return StatusCode::SUCCESS;
-}
+    float hit_charge = hit->integral()/50.0; // divide by 50 ohms to get charge
+    ATH_MSG_DEBUG("calo_hit filled has charge of " << hit_charge << " pC");
 
-const xAOD::WaveformHit* 
-CaloRecAlg::findPeakHit(const xAOD::WaveformHitContainer& hitContainer) const {
+    float HVgain_extrap = extrapolateHVgain(hit->channel());
+    ATH_MSG_DEBUG("HV gain = " << HVgain_extrap );
 
-  const xAOD::WaveformHit* peakHit = NULL;
-  for( const auto& hit : hitContainer ) {
-    if (peakHit == NULL) {
-      peakHit = hit;
-    } else {
-      if ( hit->peak() > peakHit->peak() ) peakHit = hit;
-    }
-  }
+    float MIPcharge_ref = m_recoCalibTool->getMIPcharge_ref(hit->channel());
+    float hit_MIP = (hit_charge * HVgain_extrap) / MIPcharge_ref;
+    ATH_MSG_DEBUG("Edep in MIPs = " << hit_MIP );
 
-  // Didn't find anything?
-  if (peakHit == NULL) return NULL;
-  if (peakHit->status_bit(xAOD::WaveformStatus::THRESHOLD_FAILED)) return NULL;
-  return peakHit;
-}
+    float hit_Edep = hit_MIP * m_MIP_sim_Edep_calo;
+    ATH_MSG_DEBUG("Edep in GeV = " << hit_Edep );
 
-//----------------------------------------------------------------------
-float CaloRecAlg::getHV(const EventContext& ctx, int channel) const {
+    calo_hit->set_Edep(hit_Edep);  // set calibrated Edep value
 
-  ATH_MSG_DEBUG("in getHV("<<channel<<")");
+    float hit_raw_Edep = 0.0;
+    if (hit->integral() != 0.0) { // avoid possibility of division by zero error
+        float hit_raw_Edep = hit_Edep * (hit->raw_integral() / hit->integral());
+    }
+    calo_hit->set_raw_Edep(hit_raw_Edep);  // set calibrated Edep value
 
-  float HV=0.;
+    calo_hit->set_channel(hit->channel());  // set calibrated Edep value
 
-  // Read Cond Handle
-  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_PMT_HV_ReadKey, ctx};
-  const CondAttrListCollection* readCdo{*readHandle}; 
-  if (readCdo==nullptr) {
-    ATH_MSG_FATAL("Null pointer to the read conditions object");
-    return HV;
-  }
-  // Get the validitiy range
-  EventIDRange rangeW;
-  if (not readHandle.range(rangeW)) {
-    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
-    return HV;
+    calo_hit->clearWaveformLinks();
+    calo_hit->addHit(caloWaveHitHandle.get(), hit);  // create link to calo waveform hit
   }
-  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
-  ATH_MSG_DEBUG("Range of input is " << rangeW);
 
-  // Read offset for specific channel
-  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
+  ATH_MSG_DEBUG("CaloHitContainer '" << caloHitContainerHandle.name() << "' filled with "<< caloHitContainerHandle->size() <<" items");
 
-  if (payload.exists("HV") and not payload["HV"].isNull()) {
-    HV = payload["HV"].data<float>();
-    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", HV as " << HV);
-  } else {
-    ATH_MSG_WARNING("No valid HV found for channel "<<channel<<"!");
-  }
+  for( const auto& hit : *preshowerWaveHitHandle ) {
+    if (hit->status_bit(xAOD::WaveformStatus::SECONDARY)) continue;
 
-  return HV;
+    // Create a new preshower hit
+    xAOD::CalorimeterHit* preshower_hit = new xAOD::CalorimeterHit();
+    preshowerHitContainerHandle->push_back(preshower_hit);
 
-}
+    ATH_MSG_DEBUG("preshower_hit in channel " << hit->channel() );
 
-float CaloRecAlg::getHV(int channel) const {
-  const EventContext& ctx(Gaudi::Hive::currentContext());
-  return CaloRecAlg::getHV(ctx, channel);
-}
+    float hit_charge = hit->integral()/50.0; // divide by 50 ohms to get charge
+    ATH_MSG_DEBUG("preshower_hit filled has charge of " << hit_charge << " pC");
 
-//----------------------------------------------------------------------
-float CaloRecAlg::getHV_ref(const EventContext& ctx, int channel) const {
-
-  ATH_MSG_DEBUG("in getHV_ref("<<channel<<")");
+    float MIPcharge_ref = m_recoCalibTool->getMIPcharge_ref(hit->channel());
+    float hit_MIP = hit_charge / MIPcharge_ref;
+    ATH_MSG_DEBUG("Edep in MIPs = " << hit_MIP );
 
-  float HV_ref=0.;
+    float hit_Edep = hit_MIP * m_MIP_sim_Edep_preshower;
+    ATH_MSG_DEBUG("Edep in GeV = " << hit_Edep );
 
-  // Read Cond Handle
-  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_PMT_HV_ref_ReadKey, ctx};
-  const CondAttrListCollection* readCdo{*readHandle};
-  if (readCdo==nullptr) {
-    ATH_MSG_FATAL("Null pointer to the read conditions object");
-    return HV_ref;
-  }
-  // Get the validitiy range
-  EventIDRange rangeW;
-  if (not readHandle.range(rangeW)) {
-    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
-    return HV_ref;
-  }
-  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
-  ATH_MSG_DEBUG("Range of input is " << rangeW);
+    preshower_hit->set_Edep(hit_Edep);  // set calibrated Edep value
 
-  // Read offset for specific channel
-  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
+    float hit_raw_Edep = 0.0;
+    if (hit->integral() != 0.0) { // avoid possibility of division by zero error
+        float hit_raw_Edep = hit_Edep * (hit->raw_integral() / hit->integral());
+    }
+    preshower_hit->set_raw_Edep(hit_raw_Edep);  // set calibrated Edep value
+    
+    preshower_hit->set_channel(hit->channel());  // set calibrated Edep value
 
-  if (payload.exists("HV_ref") and not payload["HV_ref"].isNull()) {
-    HV_ref = payload["HV_ref"].data<float>();
-    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", HV_ref as " << HV_ref);
-  } else {
-    ATH_MSG_WARNING("No valid HV_ref found for channel "<<channel<<"!");
+    preshower_hit->clearWaveformLinks();
+    preshower_hit->addHit(preshowerWaveHitHandle.get(), hit);  // create link to preshower waveform hit
   }
 
-  return HV_ref;
+  ATH_MSG_DEBUG("PreshowerHitContainer '" << preshowerHitContainerHandle.name() << "' filled with "<< preshowerHitContainerHandle->size() <<" items");
 
-}
 
-float CaloRecAlg::getHV_ref(int channel) const {
-  const EventContext& ctx(Gaudi::Hive::currentContext());
-  return CaloRecAlg::getHV_ref(ctx, channel);
+  return StatusCode::SUCCESS;
 }
 
 //----------------------------------------------------------------------
-float CaloRecAlg::getMIPcharge_ref(const EventContext& ctx, int channel) const {
-
-  ATH_MSG_DEBUG("in getMIPcharge_ref("<<channel<<")");
-
-  float MIP_charge_ref =0.;
-
-  // Read Cond Handle
-  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_MIPcharge_ref_ReadKey, ctx};
-  const CondAttrListCollection* readCdo{*readHandle};
-  if (readCdo==nullptr) {
-    ATH_MSG_FATAL("Null pointer to the read conditions object");
-    return MIP_charge_ref;
-  }
-  // Get the validitiy range
-  EventIDRange rangeW;
-  if (not readHandle.range(rangeW)) {
-    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
-    return MIP_charge_ref;
-  }
-  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
-  ATH_MSG_DEBUG("Range of input is " << rangeW);
+float CaloRecAlg::extrapolateHVgain(int channel) const {
+  float PMT_hv = m_recoCalibTool->getHV(channel);
+  float PMT_hv_ref = m_recoCalibTool->getHV_ref(channel);
+  TF1 gaincurve = m_recoCalibTool->get_PMT_HV_curve(channel);
 
-  // Read offset for specific channel
-  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
-
-  if (payload.exists("MIP_charge_ref") and not payload["MIP_charge_ref"].isNull()) {
-    MIP_charge_ref = payload["MIP_charge_ref"].data<float>();
-    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", MIP_charge_ref as " << MIP_charge_ref);
-  } else {
-    ATH_MSG_WARNING("No valid MIP_charge_ref found for channel "<<channel<<"!");
-  }
-
-  return MIP_charge_ref;
+  float gaincurve_atHV = gaincurve.Eval(PMT_hv);
+  float gaincurve_atHVref = gaincurve.Eval(PMT_hv_ref);
 
+  return ( gaincurve_atHVref / gaincurve_atHV ) * pow( PMT_hv_ref / PMT_hv , 6.6);
 }
-
-float CaloRecAlg::getMIPcharge_ref(int channel) const {
-  const EventContext& ctx(Gaudi::Hive::currentContext());
-  return CaloRecAlg::getMIPcharge_ref(ctx, channel);
-}
-
-
-
-
 //----------------------------------------------------------------------
 
-
-
diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
index f68c84ed8..cc705afcd 100644
--- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
+++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
@@ -12,7 +12,7 @@
 #include "xAODFaserCalorimeter/CalorimeterHitAuxContainer.h"
 
 // Tool classes
-//#include "CaloRecTools/ICalorimeterReconstructionTool.h"
+#include "CaloRecTools/ICaloRecTool.h"
 
 // Include Athena stuff for Conditions db reading
 #include "AthenaPoolUtilities/CondAttrListCollection.h"
@@ -29,9 +29,12 @@
 #include "GaudiKernel/ICondSvc.h"
 #include "Gaudi/Property.h"
 
+// ROOT
+#include "TF1.h"
 
 // STL
 #include <string>
+#include <vector>
 
 class CaloRecAlg : public AthReentrantAlgorithm {
 
@@ -59,46 +62,31 @@ class CaloRecAlg : public AthReentrantAlgorithm {
   /**
    * @name Reconstruction tool
    */
-  //ToolHandle<ICalorimeterReconstructionTool> m_recoTool
-  //{this, "CalorimeterReconstructionTool", "CalorimeterReconstructionTool"};
+  ToolHandle<ICaloRecTool> m_recoCalibTool {this, "CaloRecTool", "CaloRecTool"};
 
   /**
    * @name Input raw waveform data using SG::ReadHandleKey
    */
   //@{
-  SG::ReadHandleKey<xAOD::WaveformHitContainer> m_caloWaveHitContainerKey
-    {this, "CaloWaveHitContainerKey", ""};
+  SG::ReadHandleKey<xAOD::WaveformHitContainer> m_caloWaveHitContainerKey {this, "CaloWaveHitContainerKey", "CaloWaveformHits"};
   //@}
 
   //@{
-  SG::ReadHandleKey<xAOD::WaveformHitContainer> m_preshowerWaveHitContainerKey
-    {this, "PreshowerWaveHitContainerKey", ""};
+  SG::ReadHandleKey<xAOD::WaveformHitContainer> m_preshowerWaveHitContainerKey {this, "PreshowerWaveHitContainerKey", "PreshowerWaveformHits"};
   //@}
 
   /**
    * @name Output data using SG::WriteHandleKey
    */
   //@{
-  SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_caloHitContainerKey
-    {this, "CaloHitContainerKey", ""};
+  SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_caloHitContainerKey {this, "CaloHitContainerKey", "CaloHits"};
+  SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_preshowerHitContainerKey {this, "PreshowerHitContainerKey", "PreshowerHits"};
   //@}
 
-  const xAOD::WaveformHit* 
-    findPeakHit(const xAOD::WaveformHitContainer& hitContainer) const;
+  float extrapolateHVgain(int channel) const;
 
-  virtual float getHV(const EventContext& ctx, int channel) const;
-  virtual float getHV(int channel) const;
-
-  virtual float getHV_ref(const EventContext& ctx, int channel) const;
-  virtual float getHV_ref(int channel) const;
-
-  virtual float getMIPcharge_ref(const EventContext& ctx, int channel) const;
-  virtual float getMIPcharge_ref(int channel) const;
-
-  // Read Cond Handle
-  SG::ReadCondHandleKey<CondAttrListCollection> m_PMT_HV_ReadKey{this, "PMT_HV_ReadKey", "/WAVE/Calibration/HV", "Key of folder for PMT HV reading"};
-  SG::ReadCondHandleKey<CondAttrListCollection> m_PMT_HV_ref_ReadKey{this, "PMT_HV_ref_ReadKey", "/WAVE/Calibration/HV_ref", "Key of folder for PMT HV at time of MIP calibration measurement"};
-  SG::ReadCondHandleKey<CondAttrListCollection> m_MIPcharge_ref_ReadKey{this, "MIPcharge_ref_ReadKey", "/WAVE/Calibration/MIP_charge_ref", "Key of folder for MIPcharge calibration measurment"};
+  FloatProperty m_MIP_sim_Edep_calo {this, "MIP_sim_Edep_calo", 0.0585}; // MIP deposits 0.0585 GeV of energy in calo
+  FloatProperty m_MIP_sim_Edep_preshower {this, "MIP_sim_Edep_preshower", 0.004894}; // MIP deposits 0.004894 GeV of energy in a preshower layer
 
 };
 
diff --git a/Calorimeter/CaloRecTools/CMakeLists.txt b/Calorimeter/CaloRecTools/CMakeLists.txt
index 36c9f1dcd..f0e9f07b5 100644
--- a/Calorimeter/CaloRecTools/CMakeLists.txt
+++ b/Calorimeter/CaloRecTools/CMakeLists.txt
@@ -1,5 +1,5 @@
 ################################################################################
-# Package: WaveRecTools
+# Package: CaloRecTools
 ################################################################################
 
 # Declare the package name:
@@ -13,15 +13,18 @@ atlas_add_library( CaloRecToolsLib
                    CaloRecTools/*.h src/*.cxx src/*.h
                    PUBLIC_HEADERS CaloRecTools
                    PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-                   LINK_LIBRARIES AthenaBaseComps AthenaKernel GeoPrimitives Identifier
+                   LINK_LIBRARIES AthenaBaseComps AthenaPoolUtilities AthenaKernel GaudiKernel
                    PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES}
-		   )
+       		   )
 
 atlas_add_component( CaloRecTools
 		     src/components/*.cxx 
 		     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
                      LINK_LIBRARIES ${ROOT_LIBRARIES} 
-		     AthenaBaseComps GaudiKernel 
+		     AthenaBaseComps AthenaPoolUtilities AthenaKernel GaudiKernel 
 		     CaloRecToolsLib)
 
+# Install files from the package:
+atlas_install_python_modules( python/*.py )
+
 
diff --git a/Calorimeter/CaloRecTools/CaloRecTools/ICaloRecTool.h b/Calorimeter/CaloRecTools/CaloRecTools/ICaloRecTool.h
new file mode 100644
index 000000000..feb141d91
--- /dev/null
+++ b/Calorimeter/CaloRecTools/CaloRecTools/ICaloRecTool.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2022 CERN for the benefit of the FASER collaboration
+*/
+
+/**
+ * @file ICaloRecTool.h
+ * Header file for the ICaloRecTool class
+ * @author Deion Fellers, 2022
+ */
+
+
+#ifndef CALORECTOOL_ICALORECTOOL_H
+#define CALORECTOOL_ICALORECTOOL_H
+
+// Base class
+#include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/EventContext.h"
+
+#include "TF1.h"
+
+///Interface for Calo reco algorithms
+class ICaloRecTool : virtual public IAlgTool 
+{
+  public:
+
+  // InterfaceID
+  DeclareInterfaceID(ICaloRecTool, 1, 0);
+
+  virtual ~ICaloRecTool() = default; //!< Destructor
+
+  // methods to return calibration database data
+  virtual float getHV(const EventContext& ctx, int channel) const = 0;
+  virtual float getHV(int channel) const = 0;
+
+  virtual float getHV_ref(const EventContext& ctx, int channel) const = 0;
+  virtual float getHV_ref(int channel) const = 0;
+
+  virtual float getMIPcharge_ref(const EventContext& ctx, int channel) const = 0;
+  virtual float getMIPcharge_ref(int channel) const = 0;
+
+  virtual TF1 get_PMT_HV_curve(int channel) const = 0;
+};
+
+#endif // CALORECTOOL_ICALORECTOOL_H
diff --git a/Calorimeter/CaloRecTools/CaloRecTools/ICaloReconstructionTool.h b/Calorimeter/CaloRecTools/CaloRecTools/ICaloReconstructionTool.h
deleted file mode 100644
index d6decfbd0..000000000
--- a/Calorimeter/CaloRecTools/CaloRecTools/ICaloReconstructionTool.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-  Copyright (C) 2021 CERN for the benefit of the FASER collaboration
-*/
-
-/**
- * @file ICaloReconstructionTool.h
- * Header file for the ICaloReconstructionTool class
- * @author Eric Torrence, 2021
- */
-
-
-#ifndef CALORECTOOLS_ICALOCONSTRUCTIONTOOL_H
-#define CALORECTOOLS_ICALOCONSTRUCTIONTOOL_H
-
-// Base class
-#include "GaudiKernel/IAlgTool.h"
-#include "GaudiKernel/ToolHandle.h"
-
-///Interface for Calo reco algorithms
-class ICaloReconstructionTool : virtual public IAlgTool 
-{
-  public:
-
-  // InterfaceID
-  DeclareInterfaceID(ICaloReconstructionTool, 1, 0);
-
-  virtual ~ICaloReconstructionTool() = default;
-
-};
-
-#endif // SCINTRECTOOLS_IWAVEFORMRECONSTRUCTIONTOOL_H
diff --git a/Calorimeter/CaloRecTools/python/CaloRecToolConfig.py b/Calorimeter/CaloRecTools/python/CaloRecToolConfig.py
new file mode 100644
index 000000000..e87ac3658
--- /dev/null
+++ b/Calorimeter/CaloRecTools/python/CaloRecToolConfig.py
@@ -0,0 +1,28 @@
+""" Define methods to configure CaloRecTool
+
+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
+CaloRecTool=CompFactory.CaloRecTool
+
+
+def CaloRecToolCfg(flags, name="CaloRecTool", **kwargs):
+    """ Return configured ComponentAccumulator and tool for Calo Calibration 
+
+    CaloRecTool may be provided in kwargs
+    """
+
+    acc = ComponentAccumulator()
+    # tool = kwargs.get("CaloRecTool", CaloRecTool(flags))
+    # Probably need to figure this out!
+    dbInstance = kwargs.get("dbInstance", "TRIGGER_OFL")
+
+    acc.merge(addFolders(flags, "/WAVE/Calibration/HV", dbInstance, className="CondAttrListCollection"))
+    acc.merge(addFolders(flags, "/WAVE/Calibration/HV_ref", dbInstance, className="CondAttrListCollection"))
+    acc.merge(addFolders(flags, "/WAVE/Calibration/MIP_charge_ref", dbInstance, className="CondAttrListCollection"))
+
+    return acc
+
+
diff --git a/Calorimeter/CaloRecTools/src/CaloRecTool.cxx b/Calorimeter/CaloRecTools/src/CaloRecTool.cxx
new file mode 100644
index 000000000..b7b491644
--- /dev/null
+++ b/Calorimeter/CaloRecTools/src/CaloRecTool.cxx
@@ -0,0 +1,195 @@
+/*
+  Copyright (C) 2022 CERN for the benefit of the FASER collaboration
+*/
+
+/**
+ * @file CaloRecTool.cxx
+ * Implementation file for the CaloRecTool.cxx
+ * @ author Deion Fellers, 2022
+ **/
+
+#include "CaloRecTool.h"
+
+// Constructor
+CaloRecTool::CaloRecTool(const std::string& type, const std::string& name, const IInterface* parent) :
+  base_class(type, name, parent)
+{
+}
+
+//--------------------------------------------------------------
+StatusCode
+CaloRecTool::initialize() {
+  ATH_MSG_INFO( name() << "::initalize()" );
+
+  // Set keys to read calibratiion variables from data base
+  ATH_CHECK( m_PMT_HV_ReadKey.initialize() );
+  ATH_CHECK( m_PMT_HV_ref_ReadKey.initialize() );
+  ATH_CHECK( m_MIPcharge_ref_ReadKey.initialize() );
+
+  // access and store calo PMT HV gain curves
+  HVgaincurves_rootFile = TFile::Open("CaloGainCurves.root","read");   // open root file that has TF1 gain curves stored
+
+  chan0_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan0_HVgaincurve_name.value().c_str()); // make pointers to the gain curves
+  chan1_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan1_HVgaincurve_name.value().c_str());
+  chan2_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan2_HVgaincurve_name.value().c_str());
+  chan3_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan3_HVgaincurve_name.value().c_str());
+
+  m_HVgainCurveMap[0] = *chan0_HVgaincurve_pntr;  // store TF1 objects in an array mapped to the calo channel numbers
+  m_HVgainCurveMap[1] = *chan1_HVgaincurve_pntr;
+  m_HVgainCurveMap[2] = *chan2_HVgaincurve_pntr;
+  m_HVgainCurveMap[3] = *chan3_HVgaincurve_pntr;
+
+  HVgaincurves_rootFile->Close(); // close the root file
+
+
+  return StatusCode::SUCCESS;
+}
+
+//--------------------------------------------------------------
+StatusCode
+CaloRecTool::finalize() {
+  // Print where you are
+  return StatusCode::SUCCESS;
+}
+
+//--------------------------------------------------------------
+TF1 CaloRecTool::get_PMT_HV_curve(int channel) const {
+  if (channel <= 4) {
+    return m_HVgainCurveMap[channel];
+  } else {
+    ATH_MSG_WARNING("channel "<<channel<<" is not <= 4 and thus not a calorimeter channel, so no HV gain-curve exists!");
+  }
+  return TF1("default", "1.0", 0.0, 2000.0);
+}
+
+//--------------------------------------------------------------
+float CaloRecTool::getHV(const EventContext& ctx, int channel) const {
+
+  ATH_MSG_DEBUG("in getHV("<<channel<<")");
+
+  float HV=0.;
+
+  // Read Cond Handle
+  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_PMT_HV_ReadKey, ctx};
+  const CondAttrListCollection* readCdo{*readHandle}; 
+  if (readCdo==nullptr) {
+    ATH_MSG_FATAL("Null pointer to the read conditions object");
+    return HV;
+  }
+  // Get the validitiy range
+  EventIDRange rangeW;
+  if (not readHandle.range(rangeW)) {
+    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
+    return HV;
+  }
+  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
+  ATH_MSG_DEBUG("Range of input is " << rangeW);
+
+  // Read offset for specific channel
+  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
+
+  if (payload.exists("HV") and not payload["HV"].isNull()) {
+    HV = payload["HV"].data<float>();
+    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", HV as " << HV);
+  } else {
+    ATH_MSG_WARNING("No valid HV found for channel "<<channel<<"!");
+  }
+
+  return HV;
+
+}
+
+float CaloRecTool::getHV(int channel) const {
+  const EventContext& ctx(Gaudi::Hive::currentContext());
+  return CaloRecTool::getHV(ctx, channel);
+}
+
+//----------------------------------------------------------------------
+float CaloRecTool::getHV_ref(const EventContext& ctx, int channel) const {
+
+  ATH_MSG_DEBUG("in getHV_ref("<<channel<<")");
+
+  float HV_ref=0.;
+
+  // Read Cond Handle
+  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_PMT_HV_ref_ReadKey, ctx};
+  const CondAttrListCollection* readCdo{*readHandle};
+  if (readCdo==nullptr) {
+    ATH_MSG_FATAL("Null pointer to the read conditions object");
+    return HV_ref;
+  }
+  // Get the validitiy range
+  EventIDRange rangeW;
+  if (not readHandle.range(rangeW)) {
+    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
+    return HV_ref;
+  }
+  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
+  ATH_MSG_DEBUG("Range of input is " << rangeW);
+
+  // Read offset for specific channel
+  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
+
+  if (payload.exists("HV_ref") and not payload["HV_ref"].isNull()) {
+    HV_ref = payload["HV_ref"].data<float>();
+    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", HV_ref as " << HV_ref);
+  } else {
+    ATH_MSG_WARNING("No valid HV_ref found for channel "<<channel<<"!");
+  }
+
+  return HV_ref;
+
+}
+
+float CaloRecTool::getHV_ref(int channel) const {
+  const EventContext& ctx(Gaudi::Hive::currentContext());
+  return CaloRecTool::getHV_ref(ctx, channel);
+}
+
+//----------------------------------------------------------------------
+float CaloRecTool::getMIPcharge_ref(const EventContext& ctx, int channel) const {
+
+  ATH_MSG_DEBUG("in getMIPcharge_ref("<<channel<<")");
+
+  float MIP_charge_ref =0.;
+
+  // Read Cond Handle
+  SG::ReadCondHandle<CondAttrListCollection> readHandle{m_MIPcharge_ref_ReadKey, ctx};
+  const CondAttrListCollection* readCdo{*readHandle};
+  if (readCdo==nullptr) {
+    ATH_MSG_FATAL("Null pointer to the read conditions object");
+    return MIP_charge_ref;
+  }
+  // Get the validitiy range
+  EventIDRange rangeW;
+  if (not readHandle.range(rangeW)) {
+    ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key());
+    return MIP_charge_ref;
+  }
+  ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size());
+  ATH_MSG_DEBUG("Range of input is " << rangeW);
+
+  // Read offset for specific channel
+  const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)};
+
+  if (payload.exists("MIP_charge_ref") and not payload["MIP_charge_ref"].isNull()) {
+    MIP_charge_ref = payload["MIP_charge_ref"].data<float>();
+    ATH_MSG_DEBUG("Found digitizer channel " << channel << ", MIP_charge_ref as " << MIP_charge_ref);
+  } else {
+    ATH_MSG_WARNING("No valid MIP_charge_ref found for channel "<<channel<<"!");
+  }
+
+  return MIP_charge_ref;
+
+}
+
+float CaloRecTool::getMIPcharge_ref(int channel) const {
+  const EventContext& ctx(Gaudi::Hive::currentContext());
+  return CaloRecTool::getMIPcharge_ref(ctx, channel);
+}
+
+//--------------------------------------------------------------
+
+
+
+
diff --git a/Calorimeter/CaloRecTools/src/CaloRecTool.h b/Calorimeter/CaloRecTools/src/CaloRecTool.h
new file mode 100644
index 000000000..28a2221c1
--- /dev/null
+++ b/Calorimeter/CaloRecTools/src/CaloRecTool.h
@@ -0,0 +1,83 @@
+/*
+   Copyright (C) 2021 CERN for the benefit of the FASER collaboration
+*/
+
+/** @file CaloRecTool.h
+ *  Header file for CaloRecTool.h
+ *
+ */
+#ifndef CALORECTOOLS_CALORECTOOL_H
+#define CALORECTOOLS_CALORECTOOL_H
+
+// Include interface class
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "CaloRecTools/ICaloRecTool.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/ICondSvc.h"
+#include "Gaudi/Property.h"
+#include "GaudiKernel/EventContext.h"
+
+// Include ROOT classes
+#include "TF1.h"
+#include "TFile.h"
+
+#include <string>
+
+class CaloRecTool: public extends<AthAlgTool, ICaloRecTool> {
+ public:
+
+  /// Normal constructor for an AlgTool; 'properties' are also declared here
+  CaloRecTool(const std::string& type, const std::string& name, const IInterface* parent);
+
+  // Standard Gaudi functions
+  virtual StatusCode initialize() override; //!< Gaudi initialiser
+  virtual StatusCode finalize() override; //!< Gaudi finaliser
+
+  // methods for returning calibration data
+  // Channels indexed by digitizer channel number
+  // HV is in Volts and MIPcharge is in pC
+  //
+  virtual float getHV(const EventContext& ctx, int channel) const override;
+  virtual float getHV(int channel) const override;
+
+  virtual float getHV_ref(const EventContext& ctx, int channel) const override;
+  virtual float getHV_ref(int channel) const override;
+
+  virtual float getMIPcharge_ref(const EventContext& ctx, int channel) const override;
+  virtual float getMIPcharge_ref(int channel) const override;
+
+  // method for returning PMT HV calibration curves from root file
+  virtual TF1 get_PMT_HV_curve(int channel) const override;
+
+  TFile* HVgaincurves_rootFile;
+
+  TF1* chan0_HVgaincurve_pntr;
+  TF1* chan1_HVgaincurve_pntr;
+  TF1* chan2_HVgaincurve_pntr;
+  TF1* chan3_HVgaincurve_pntr;
+
+  TF1 m_HVgainCurveMap[4];
+
+  private:
+  // properties that map channel name to PMT HV gain curves. PMt names found at https://twiki.cern.ch/twiki/bin/viewauth/FASER/CaloScintillator
+  StringProperty m_chan0_HVgaincurve_name{this, "Chan0HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8770"};
+  StringProperty m_chan1_HVgaincurve_name{this, "Chan1HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8733"};
+  StringProperty m_chan2_HVgaincurve_name{this, "Chan2HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8786"};
+  StringProperty m_chan3_HVgaincurve_name{this, "Chan3HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8732"};
+
+  // Read Cond Handle
+  SG::ReadCondHandleKey<CondAttrListCollection> m_PMT_HV_ReadKey{this, "PMT_HV_ReadKey", "/WAVE/Calibration/HV", "Key of folder for PMT HV reading"};
+  SG::ReadCondHandleKey<CondAttrListCollection> m_PMT_HV_ref_ReadKey{this, "PMT_HV_ref_ReadKey", "/WAVE/Calibration/HV_ref", "Key of folder for PMT HV at time of MIP calibration measurement"};
+  SG::ReadCondHandleKey<CondAttrListCollection> m_MIPcharge_ref_ReadKey{this, "MIPcharge_ref_ReadKey", "/WAVE/Calibration/MIP_charge_ref", "Key of folder for MIPcharge calibration measurment"};
+
+};
+
+#endif // CALORECTOOLS_CALORECTOOL_H
diff --git a/Calorimeter/CaloRecTools/src/CaloReconstructionTool.cxx b/Calorimeter/CaloRecTools/src/CaloReconstructionTool.cxx
deleted file mode 100644
index 438dd77f3..000000000
--- a/Calorimeter/CaloRecTools/src/CaloReconstructionTool.cxx
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-  Copyright (C) 2021 CERN for the benefit of the FASER collaboration
-*/
-
-/**
- * @file CaloReconstructionTool.cxx
- * Implementation file for the CaloReconstructionTool.cxx
- * @ author E. Torrence, 2021
- **/
-
-#include "CaloReconstructionTool.h"
-
-#include "TH1F.h"
-#include "TF1.h"
-#include "TFitResult.h"
-#include "TFitResultPtr.h"
-#include "TGraph.h"
-#include "TError.h"
-
-#include <vector>
-#include <tuple>
-#include <math.h>
-
-// Constructor
-CaloReconstructionTool::CaloReconstructionTool(const std::string& type, const std::string& name, const IInterface* parent) :
-  base_class(type, name, parent)
-{
-}
-
-// Initialization
-StatusCode
-CaloReconstructionTool::initialize() {
-  ATH_MSG_INFO( name() << "::initalize()" );
-
-  return StatusCode::SUCCESS;
-}
-
-
diff --git a/Calorimeter/CaloRecTools/src/CaloReconstructionTool.h b/Calorimeter/CaloRecTools/src/CaloReconstructionTool.h
deleted file mode 100644
index 55ea137ef..000000000
--- a/Calorimeter/CaloRecTools/src/CaloReconstructionTool.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-   Copyright (C) 2021 CERN for the benefit of the FASER collaboration
-*/
-
-/** @file CaloReconstructionTool.h
- *  Header file for CaloReconstructionTool.h
- *
- */
-#ifndef CALORECTOOLS_CALORECONSTRUCTIONTOOL_H
-#define CALORECTOOLS_CALORECONSTRUCTIONTOOL_H
-
-//Athena
-#include "AthenaBaseComps/AthAlgTool.h"
-#include "CaloRecTools/ICaloReconstructionTool.h"
-
-//Gaudi
-#include "GaudiKernel/ToolHandle.h"
-
-//STL
-#include <string>
-#include <vector>
-
-class CaloReconstructionTool: public extends<AthAlgTool, ICaloReconstructionTool> {
- public:
-
-  /// Normal constructor for an AlgTool; 'properties' are also declared here
-  CaloReconstructionTool(const std::string& type, 
-			     const std::string& name, const IInterface* parent);
-
-  /// Retrieve the necessary services in initialize
-  StatusCode initialize();
-
- private:
-
-
-};
-
-#endif // CALORECTOOLS_CALOCONSTRUCTIONTOOL_H
diff --git a/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx b/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx
index 183a4878b..c9c5438eb 100644
--- a/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx
+++ b/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx
@@ -1,3 +1,3 @@
-#include "../CaloReconstructionTool.h"
+#include "../CaloRecTool.h"
 
-DECLARE_COMPONENT( CaloReconstructionTool )
+DECLARE_COMPONENT( CaloRecTool )
diff --git a/xAOD/xAODFaserCalorimeter/Root/CalorimeterHitAuxContainer_v1.cxx b/xAOD/xAODFaserCalorimeter/Root/CalorimeterHitAuxContainer_v1.cxx
index 6f6edf3e4..f73a83dd1 100644
--- a/xAOD/xAODFaserCalorimeter/Root/CalorimeterHitAuxContainer_v1.cxx
+++ b/xAOD/xAODFaserCalorimeter/Root/CalorimeterHitAuxContainer_v1.cxx
@@ -10,11 +10,11 @@ namespace xAOD {
   CalorimeterHitAuxContainer_v1::CalorimeterHitAuxContainer_v1() 
     : AuxContainerBase() {
 
-    AUX_VARIABLE(localtime);
-    AUX_VARIABLE(bcid_time);
-    AUX_VARIABLE(raw_energy);
+    AUX_VARIABLE(channel);
+    AUX_VARIABLE(Edep);
+    AUX_VARIABLE(raw_Edep);
 
-    AUX_VARIABLE(caloLinks);
+    AUX_VARIABLE(WaveformLink);
   }
 
 } // namespace xAOD
diff --git a/xAOD/xAODFaserCalorimeter/Root/CalorimeterHit_v1.cxx b/xAOD/xAODFaserCalorimeter/Root/CalorimeterHit_v1.cxx
index 5e7a69ecc..f085cb0c9 100644
--- a/xAOD/xAODFaserCalorimeter/Root/CalorimeterHit_v1.cxx
+++ b/xAOD/xAODFaserCalorimeter/Root/CalorimeterHit_v1.cxx
@@ -13,41 +13,41 @@ namespace xAOD {
   CalorimeterHit_v1::CalorimeterHit_v1() : SG::AuxElement() {
   }
 
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, localtime, set_localtime )
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, unsigned int, channel, set_channel )
 
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, bcidtime, set_bcidtime )
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, Edep, set_Edep )
 
-  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, raw_energy, set_raw_energy )
+  AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, raw_Edep, set_raw_Edep )
 
   // setters and getters for the Calo WaveformHit links
 
   AUXSTORE_OBJECT_SETTER_AND_GETTER( CalorimeterHit_v1,
 				     CalorimeterHit_v1::WaveformHitLinks_t,
-				     caloWaveformLinks,
-				     setCaloWaveformLinks )
+				     WaveformLinks,
+				     setWaveformLinks )
 
-  static const SG::AuxElement::Accessor< CalorimeterHit_v1::WaveformHitLinks_t > caloHitAcc( "caloWaveformLinks" );
+  static const SG::AuxElement::Accessor< CalorimeterHit_v1::WaveformHitLinks_t > HitAcc( "WaveformLinks" );
 
-  const WaveformHit* CalorimeterHit_v1::caloHit( size_t i ) const {
-    return ( *caloHitAcc( *this )[ i ] );
+  const WaveformHit* CalorimeterHit_v1::Hit( size_t i ) const {
+    return ( *HitAcc( *this )[ i ] );
   }
 
-  size_t CalorimeterHit_v1::nCaloHits() const {
-    return caloHitAcc( *this ).size();
+  size_t CalorimeterHit_v1::nHits() const {
+    return HitAcc( *this ).size();
   }
 
-  void CalorimeterHit_v1::addCaloHit( const xAOD::WaveformHitContainer* pWaveformHitContainer, 
+  void CalorimeterHit_v1::addHit( const xAOD::WaveformHitContainer* pWaveformHitContainer, 
 				      const xAOD::WaveformHit* pWaveformHit) {
     ElementLink< xAOD::WaveformHitContainer > linkToWaveformHit;
     linkToWaveformHit.toContainedElement(*pWaveformHitContainer, pWaveformHit);
 
-    caloHitAcc( *this ).push_back( linkToWaveformHit );
+    HitAcc( *this ).push_back( linkToWaveformHit );
 
     return;
   }
 
-  void CalorimeterHit_v1::clearCaloWaveformLinks() {
-    caloHitAcc( *this ).clear();
+  void CalorimeterHit_v1::clearWaveformLinks() {
+    HitAcc( *this ).clear();
     return;
   }
 
@@ -57,8 +57,8 @@ namespace xAOD {
 
   std::ostream& operator<<(std::ostream& s, const xAOD::CalorimeterHit_v1& hit) {
     s << "xAODCalorimeterHit:"
-      << " local time=" << hit.localtime()
-      << " raw_energy=" << hit.raw_energy()
+      << " channel = " << hit.channel()
+      << ", Edep = " << hit.Edep()
       << std::endl;
 
     return s;
diff --git a/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHitAuxContainer_v1.h b/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHitAuxContainer_v1.h
index 7e61261eb..41a89a032 100644
--- a/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHitAuxContainer_v1.h
+++ b/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHitAuxContainer_v1.h
@@ -29,13 +29,14 @@ namespace xAOD {
   private:
     /// @name Basic variables
     ///@ {
-    std::vector<float> localtime;
-    std::vector<float> bcid_time;
-    std::vector<float> raw_energy;
+    std::vector<unsigned int> channel;
+    std::vector<float> Edep;
+    std::vector<float> raw_Edep;
 
     typedef std::vector< ElementLink< WaveformHitContainer > > WaveformHitLink_t;
-    std::vector< WaveformHitLink_t > caloLinks;
-    std::vector< WaveformHitLink_t > preshowerLinks;
+    std::vector< WaveformHitLink_t > WaveformLink;
+    //std::vector< WaveformHitLink_t > caloLinks;
+    //std::vector< WaveformHitLink_t > preshowerLinks;
 
     ///@}
 
diff --git a/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHit_v1.h b/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHit_v1.h
index d9bb35047..fefc0d5ae 100644
--- a/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHit_v1.h
+++ b/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHit_v1.h
@@ -35,29 +35,29 @@ namespace xAOD {
     /// @{
 
     /// Best results
-    float localtime() const;
-    void set_localtime(float value);
+    unsigned int channel() const;
+    void set_channel(unsigned int value);
 
-    float bcidtime() const;
-    void set_bcidtime(float value);
+    float Edep() const;
+    void set_Edep(float value);
 
-    float raw_energy() const;
-    void set_raw_energy(float value);
+    float raw_Edep() const;
+    void set_raw_Edep(float value);
 
     // Waveform Hits
     typedef std::vector< ElementLink< xAOD::WaveformHitContainer > > WaveformHitLinks_t;
 
     // Contributing Calorimeter Waveform Hits
-    const WaveformHitLinks_t& caloWaveformLinks() const;
-    void setCaloWaveformLinks( const WaveformHitLinks_t& caloWaveforms );
+    const WaveformHitLinks_t& WaveformLinks() const;
+    void setWaveformLinks( const WaveformHitLinks_t& Waveforms );
     // Remove all waveform hits
-    void clearCaloWaveformLinks();
+    void clearWaveformLinks();
     // Get the pointer to a given waveform hit
-    const WaveformHit* caloHit( size_t i ) const;
+    const WaveformHit* Hit( size_t i ) const;
     // Get the number of waveform hits
-    size_t nCaloHits() const;
+    size_t nHits() const;
     // Add a waveform hit
-    void addCaloHit( const xAOD::WaveformHitContainer*, const xAOD::WaveformHit*);
+    void addHit( const xAOD::WaveformHitContainer*, const xAOD::WaveformHit*);
 
     // // Contributing Preshower Waveform Hits
     // const WaveformHitLinks_t& preshowerWaveformLinks() const;
-- 
GitLab


From 47537d789e1a02d9be69bf38a02da1374525e5cb Mon Sep 17 00:00:00 2001
From: Deion Elgin Fellers <dfellers@lxplus751.cern.ch>
Date: Wed, 9 Nov 2022 00:53:46 +0100
Subject: [PATCH 3/4] finalize calibration code for calo and preshower

---
 Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx   | 64 +++++++++++---------
 Calorimeter/CaloRecAlgs/src/CaloRecAlg.h     |  6 +-
 Calorimeter/CaloRecTools/src/CaloRecTool.cxx |  2 +-
 Calorimeter/CaloRecTools/src/CaloRecTool.h   |  3 +
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
index f70993055..12ddca3a4 100644
--- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
+++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx
@@ -69,11 +69,7 @@ StatusCode CaloRecAlg::execute(const EventContext& ctx) const {
   ATH_MSG_DEBUG("WaveformsHitContainer '" << caloHitContainerHandle.name() << "' initialized");
   ATH_MSG_DEBUG("WaveformsHitContainer '" << preshowerHitContainerHandle.name() << "' initialized");
 
-  // Reconstruct all waveforms
-  //CHECK( m_recoTool->reconstructAll(*waveformHandle, clockptr, hitContainerHandle.ptr()) );
-
-  ATH_MSG_DEBUG("DEION test" );
-
+  // Loop over calo hits and calibrate each primary hit
   for( const auto& hit : *caloWaveHitHandle ) {
     if (hit->status_bit(xAOD::WaveformStatus::SECONDARY)) continue;
 
@@ -83,28 +79,35 @@ StatusCode CaloRecAlg::execute(const EventContext& ctx) const {
 
     ATH_MSG_DEBUG("calo_hit in channel " << hit->channel() );
 
-    float hit_charge = hit->integral()/50.0; // divide by 50 ohms to get charge
-    ATH_MSG_DEBUG("calo_hit filled has charge of " << hit_charge << " pC");
+    float MIPcharge_ref = m_recoCalibTool->getMIPcharge_ref(hit->channel()); // get reference MIP charge from database
+
+    float hit_Edep = 0;
+    if (m_isMC) {
+      hit_Edep = hit->integral() / MIPcharge_ref; // MC MIPcharge_ref from database is really digitization scaling factors that take simulated Edep in MeV to mV*ns
+      ATH_MSG_DEBUG("isMC == True: calo hit Edep = " << hit_Edep << " MeV");
+    } else {
+      float hit_charge = hit->integral()/50.0; // divide by 50 ohms to get charge
+      ATH_MSG_DEBUG("calo_hit filled has charge of " << hit_charge << " pC");
 
-    float HVgain_extrap = extrapolateHVgain(hit->channel());
-    ATH_MSG_DEBUG("HV gain = " << HVgain_extrap );
+      float HVgain_extrap = extrapolateHVgain(hit->channel());
+      ATH_MSG_DEBUG("HV gain = " << HVgain_extrap );
 
-    float MIPcharge_ref = m_recoCalibTool->getMIPcharge_ref(hit->channel());
-    float hit_MIP = (hit_charge * HVgain_extrap) / MIPcharge_ref;
-    ATH_MSG_DEBUG("Edep in MIPs = " << hit_MIP );
+      float hit_MIP = (hit_charge * HVgain_extrap) / MIPcharge_ref;
+      ATH_MSG_DEBUG("Edep in MIPs = " << hit_MIP );
 
-    float hit_Edep = hit_MIP * m_MIP_sim_Edep_calo;
-    ATH_MSG_DEBUG("Edep in GeV = " << hit_Edep );
+      hit_Edep = hit_MIP * m_MIP_sim_Edep_calo;
+      ATH_MSG_DEBUG("Edep in MeV = " << hit_Edep );
+    }
 
     calo_hit->set_Edep(hit_Edep);  // set calibrated Edep value
 
     float hit_raw_Edep = 0.0;
     if (hit->integral() != 0.0) { // avoid possibility of division by zero error
-        float hit_raw_Edep = hit_Edep * (hit->raw_integral() / hit->integral());
+      hit_raw_Edep = hit_Edep * (hit->raw_integral() / hit->integral());
     }
-    calo_hit->set_raw_Edep(hit_raw_Edep);  // set calibrated Edep value
+    calo_hit->set_raw_Edep(hit_raw_Edep);  // set calibrated raw_Edep value
 
-    calo_hit->set_channel(hit->channel());  // set calibrated Edep value
+    calo_hit->set_channel(hit->channel());  // set channel number
 
     calo_hit->clearWaveformLinks();
     calo_hit->addHit(caloWaveHitHandle.get(), hit);  // create link to calo waveform hit
@@ -121,25 +124,32 @@ StatusCode CaloRecAlg::execute(const EventContext& ctx) const {
 
     ATH_MSG_DEBUG("preshower_hit in channel " << hit->channel() );
 
-    float hit_charge = hit->integral()/50.0; // divide by 50 ohms to get charge
-    ATH_MSG_DEBUG("preshower_hit filled has charge of " << hit_charge << " pC");
+    float MIPcharge_ref = m_recoCalibTool->getMIPcharge_ref(hit->channel()); // get reference MIP charge from database
+
+    float hit_Edep = 0;
+    if (m_isMC) {
+      hit_Edep = hit->integral() / MIPcharge_ref; // MC MIPcharge_ref from database is really digitization scaling factors that take simulated Edep in MeV to mV*ns
+      ATH_MSG_DEBUG("isMC == True: preshower hit Edep = " << hit_Edep << " MeV");
+    } else {
+      float hit_charge = hit->integral()/50.0; // divide by 50 ohms to get charge
+      ATH_MSG_DEBUG("preshower_hit filled has charge of " << hit_charge << " pC");
 
-    float MIPcharge_ref = m_recoCalibTool->getMIPcharge_ref(hit->channel());
-    float hit_MIP = hit_charge / MIPcharge_ref;
-    ATH_MSG_DEBUG("Edep in MIPs = " << hit_MIP );
+      float hit_MIP = hit_charge / MIPcharge_ref;
+      ATH_MSG_DEBUG("Edep in MIPs = " << hit_MIP );
 
-    float hit_Edep = hit_MIP * m_MIP_sim_Edep_preshower;
-    ATH_MSG_DEBUG("Edep in GeV = " << hit_Edep );
+      hit_Edep = hit_MIP * m_MIP_sim_Edep_preshower;
+      ATH_MSG_DEBUG("Edep in GeV = " << hit_Edep );
+    }
 
     preshower_hit->set_Edep(hit_Edep);  // set calibrated Edep value
 
     float hit_raw_Edep = 0.0;
     if (hit->integral() != 0.0) { // avoid possibility of division by zero error
-        float hit_raw_Edep = hit_Edep * (hit->raw_integral() / hit->integral());
+      hit_raw_Edep = hit_Edep * (hit->raw_integral() / hit->integral());
     }
-    preshower_hit->set_raw_Edep(hit_raw_Edep);  // set calibrated Edep value
+    preshower_hit->set_raw_Edep(hit_raw_Edep);  // set calibrated rsw_Edep value
     
-    preshower_hit->set_channel(hit->channel());  // set calibrated Edep value
+    preshower_hit->set_channel(hit->channel());  // set channel number
 
     preshower_hit->clearWaveformLinks();
     preshower_hit->addHit(preshowerWaveHitHandle.get(), hit);  // create link to preshower waveform hit
diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
index cc705afcd..c9ff4c514 100644
--- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
+++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h
@@ -85,8 +85,10 @@ class CaloRecAlg : public AthReentrantAlgorithm {
 
   float extrapolateHVgain(int channel) const;
 
-  FloatProperty m_MIP_sim_Edep_calo {this, "MIP_sim_Edep_calo", 0.0585}; // MIP deposits 0.0585 GeV of energy in calo
-  FloatProperty m_MIP_sim_Edep_preshower {this, "MIP_sim_Edep_preshower", 0.004894}; // MIP deposits 0.004894 GeV of energy in a preshower layer
+  FloatProperty m_MIP_sim_Edep_calo {this, "MIP_sim_Edep_calo", 58.5}; // MIP deposits 5.85 MeV of energy in calo
+  FloatProperty m_MIP_sim_Edep_preshower {this, "MIP_sim_Edep_preshower", 4.894}; // MIP deposits 4.894 MeV of energy in a preshower layer
+
+  Gaudi::Property<bool> m_isMC {this, "isMC", false};
 
 };
 
diff --git a/Calorimeter/CaloRecTools/src/CaloRecTool.cxx b/Calorimeter/CaloRecTools/src/CaloRecTool.cxx
index b7b491644..a6bb42c51 100644
--- a/Calorimeter/CaloRecTools/src/CaloRecTool.cxx
+++ b/Calorimeter/CaloRecTools/src/CaloRecTool.cxx
@@ -27,7 +27,7 @@ CaloRecTool::initialize() {
   ATH_CHECK( m_MIPcharge_ref_ReadKey.initialize() );
 
   // access and store calo PMT HV gain curves
-  HVgaincurves_rootFile = TFile::Open("CaloGainCurves.root","read");   // open root file that has TF1 gain curves stored
+  HVgaincurves_rootFile = TFile::Open(m_PMT_HV_Gain_Curve_file.value().c_str(),"read");   // open root file that has TF1 gain curves stored
 
   chan0_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan0_HVgaincurve_name.value().c_str()); // make pointers to the gain curves
   chan1_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan1_HVgaincurve_name.value().c_str());
diff --git a/Calorimeter/CaloRecTools/src/CaloRecTool.h b/Calorimeter/CaloRecTools/src/CaloRecTool.h
index 28a2221c1..c6dc95181 100644
--- a/Calorimeter/CaloRecTools/src/CaloRecTool.h
+++ b/Calorimeter/CaloRecTools/src/CaloRecTool.h
@@ -67,6 +67,9 @@ class CaloRecTool: public extends<AthAlgTool, ICaloRecTool> {
   TF1 m_HVgainCurveMap[4];
 
   private:
+  // Propert that points to the location of the root file which contains the HV gain curves for the calorimeter PMTs
+  StringProperty m_PMT_HV_Gain_Curve_file{this, "PMT_HV_Gain_Curve_file", "/cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/pmtgain/CaloGainCurves.root"};
+
   // properties that map channel name to PMT HV gain curves. PMt names found at https://twiki.cern.ch/twiki/bin/viewauth/FASER/CaloScintillator
   StringProperty m_chan0_HVgaincurve_name{this, "Chan0HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8770"};
   StringProperty m_chan1_HVgaincurve_name{this, "Chan1HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8733"};
-- 
GitLab


From f992d2a0406b2152e7a35e05a739224db98b2d82 Mon Sep 17 00:00:00 2001
From: Eric Torrence <eric.torrence@cern.ch>
Date: Sat, 12 Nov 2022 01:56:29 +0100
Subject: [PATCH 4/4] Update faser_reco.py

---
 .../Reconstruction/scripts/faser_reco.py               | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
index 8ebbc421c..8a0b5a3cd 100755
--- a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
+++ b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
@@ -180,9 +180,13 @@ acc.merge(FaserGeometryCfg(ConfigFlags))
 from WaveRecAlgs.WaveRecAlgsConfig import WaveformReconstructionCfg    
 acc.merge(WaveformReconstructionCfg(ConfigFlags))
 
-# Not ready for primetime
-from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionCfg
-acc.merge(CalorimeterReconstructionCfg(ConfigFlags))
+# Calorimeter reconstruction
+if args.isMC:
+    # Not ready for MC quite yet
+    pass
+else:
+    from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionCfg
+    acc.merge(CalorimeterReconstructionCfg(ConfigFlags))
 
 # Tracker clusters
 from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg
-- 
GitLab