From 5758cc4c3972924f14ed0b405580e3d61cb12bd9 Mon Sep 17 00:00:00 2001
From: Alexandru Bercuci <abercuci@niham.nipne.ro>
Date: Mon, 2 May 2022 21:52:01 +0200
Subject: [PATCH] add TrdHit QA data class which packs the whole history of a
 reconstructed hit from MC points to the actual data. To be used in fine
 tuning the error parametrization, pile-ups etc.

---
 reco/L1/CMakeLists.txt                     |  2 +
 reco/L1/qa/CbmTrackerInputQaTrd.cxx        | 28 +++++++--
 reco/L1/qa/CbmTrackerInputQaTrd.h          |  9 +--
 reco/detectors/trd/CMakeLists.txt          |  3 +
 reco/detectors/trd/CbmTrdRecoLinkDef.h     |  1 +
 reco/detectors/trd/qa/data/CbmTrdHitMC.cxx | 66 ++++++++++++++++++++++
 reco/detectors/trd/qa/data/CbmTrdHitMC.h   | 60 ++++++++++++++++++++
 7 files changed, 159 insertions(+), 10 deletions(-)
 create mode 100644 reco/detectors/trd/qa/data/CbmTrdHitMC.cxx
 create mode 100644 reco/detectors/trd/qa/data/CbmTrdHitMC.h

diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt
index d2602fd95d..5ac6e870c6 100644
--- a/reco/L1/CMakeLists.txt
+++ b/reco/L1/CMakeLists.txt
@@ -21,6 +21,7 @@ ${CBMROOT_SOURCE_DIR}/reco/base
 ${CBMROOT_SOURCE_DIR}/reco/detectors/sts
 ${CBMROOT_SOURCE_DIR}/reco/detectors/rich
 ${CBMROOT_SOURCE_DIR}/reco/detectors/rich/fitter
+${CBMROOT_SOURCE_DIR}/reco/detectors/trd/qa/data
 ${CBMBASE_DIR} 
 
 ${CBMDATA_DIR}
@@ -240,6 +241,7 @@ Set(DEPENDENCIES
 #    CbmGeoSetup
     CbmMuchBase
     CbmTrdBase
+    CbmTrdReco
     CbmTofBase
     CbmStsBase
     CbmRecoBase
diff --git a/reco/L1/qa/CbmTrackerInputQaTrd.cxx b/reco/L1/qa/CbmTrackerInputQaTrd.cxx
index 5ebe1fae51..8a38cc6143 100644
--- a/reco/L1/qa/CbmTrackerInputQaTrd.cxx
+++ b/reco/L1/qa/CbmTrackerInputQaTrd.cxx
@@ -22,6 +22,7 @@
 #include "CbmTrdCluster.h"
 #include "CbmTrdDigi.h"
 #include "CbmTrdHit.h"
+#include "CbmTrdHitMC.h"
 #include "CbmTrdParModDigi.h"  // for CbmTrdModule
 #include "CbmTrdParModGeo.h"
 #include "CbmTrdParSetDigi.h"  // for CbmTrdParSetDigi
@@ -118,6 +119,12 @@ void CbmTrackerInputQaTrd::DeInit()
 
   fhPointsPerHit.clear();
   fhHitsPerPoint.clear();
+
+  if (fHitsMc) {
+    fHitsMc->Clear("C");
+    fHitsMc->Delete();
+    delete fHitsMc;
+  }
 }
 // -------------------------------------------------------------------------
 
@@ -270,6 +277,10 @@ InitStatus CbmTrackerInputQaTrd::ReInit()
     return kERROR;
   }
 
+  // init output tree
+  fHitsMc = new TClonesArray("CbmTrdHitMC", 100);
+  manager->Register("TrdHitMC", "TRD", fHitsMc, IsOutputBranchPersistent("TrdHitMC"));
+
   // initialise histograms
   fOutFolder.SetOwner(false);
   fHistFolder = fOutFolder.AddFolder("rawHist", "Raw Histograms");
@@ -425,9 +436,10 @@ void CbmTrackerInputQaTrd::ResolutionQa()
   Int_t nDigis    = fDigiManager->GetNofDigis(ECbmModuleId::kTrd);
 
   int nMcEvents = fMcEventList->GetNofEvents();
+  int imc(0);  // index of hit->MC QA objects
+  fHitsMc->Delete();
 
   // Vector of integers parallel to mc points
-
   std::vector<std::vector<int>> pointNhits;
   pointNhits.resize(nMcEvents);
   for (int iE = 0; iE < nMcEvents; iE++) {
@@ -439,7 +451,7 @@ void CbmTrackerInputQaTrd::ResolutionQa()
 
   for (Int_t iHit = 0; iHit < nHits; iHit++) {
 
-    CbmTrdHit* hit = dynamic_cast<CbmTrdHit*>(fHits->At(iHit));
+    const CbmTrdHit* hit = dynamic_cast<const CbmTrdHit*>(fHits->At(iHit));
     if (!hit) {
       LOG(error) << "TRD hit N " << iHit << " doesn't exist";
       return;
@@ -553,6 +565,9 @@ void CbmTrackerInputQaTrd::ResolutionQa()
     // skip hits from the noise digis
     if (bestLink.GetIndex() < 0) { continue; }
 
+    // construct QA object
+    CbmTrdHitMC* hmc = new ((*fHitsMc)[imc++]) CbmTrdHitMC(*hit);
+
     CbmTrdPoint* p = dynamic_cast<CbmTrdPoint*>(fMcPoints->Get(bestLink));
     if (p == nullptr) {
       LOG(error) << "link points to a non-existing MC point";
@@ -631,15 +646,16 @@ void CbmTrackerInputQaTrd::ResolutionQa()
         mass = TDatabasePDG::Instance()->GetParticle(pdg)->Mass();
       }
     }
+    hmc->AddPoint(p, t0, mass);
 
     constexpr double speedOfLight = 29.979246;  // cm/ns
     TVector3 mom3;
     p->Momentum(mom3);
     t += dz / (pz * speedOfLight) * sqrt(mass * mass + mom3.Mag2());
 
-    double du = hit->GetX() - x;
-    double dv = hit->GetY() - y;
-    double dt = hit->GetTime() - t;
+    double du = hmc->GetDx();  //hit->GetX() - x;
+    double dv = hmc->GetDy();  //hit->GetY() - y;
+    double dt = hmc->GetDt();  //hit->GetTime() - t;
     double su = hit->GetDx();
     double sv = hit->GetDy();
     double st = hit->GetTimeError();
@@ -673,7 +689,7 @@ void CbmTrackerInputQaTrd::ResolutionQa()
       fh1DpullT.Fill(dt / st);
     }
     else {
-      fh2DpullX.Fill(du / su);
+      fh2DpullX.Fill(6.2 * du / su);
       fh2DpullY.Fill(dv / sv);
       fh2DpullT.Fill(dt / st);
     }
diff --git a/reco/L1/qa/CbmTrackerInputQaTrd.h b/reco/L1/qa/CbmTrackerInputQaTrd.h
index c7c6f5aad8..3404ed5b9e 100644
--- a/reco/L1/qa/CbmTrackerInputQaTrd.h
+++ b/reco/L1/qa/CbmTrackerInputQaTrd.h
@@ -106,6 +106,7 @@ private:
   TClonesArray* fHitMatches {nullptr};
 
   /// Output
+  TClonesArray* fHitsMc {nullptr};
 
 
   TFolder fOutFolder {"TrackerInputQaTrd", "TrackerInputQaTrd"};  /// output folder with histos and canvases
@@ -118,8 +119,8 @@ private:
   CbmQaHist<TH1D> fh1DresidualV {"h1DresidualV", "Trd1D: Residual V;(V_{reco} - V_{MC})(cm)", 100, -10, 10};
   CbmQaHist<TH1D> fh1DresidualT {"h1DresidualT", "Trd1D: Residual T;(T_{reco} - T_{MC})(ns)", 100, -50, 50};
 
-  CbmQaHist<TH1D> fh2DresidualX {"h2DresidualX", "Trd2D: Residual X;(X_{reco} - X_{MC})(cm)", 100, -5, 5};
-  CbmQaHist<TH1D> fh2DresidualY {"h2DresidualY", "Trd2D: Residual Y;(Y_{reco} - Y_{MC})(cm)", 100, -5, 5};
+  CbmQaHist<TH1D> fh2DresidualX {"h2DresidualX", "Trd2D: Residual X;(X_{reco} - X_{MC})(cm)", 1000, -1, 1};
+  CbmQaHist<TH1D> fh2DresidualY {"h2DresidualY", "Trd2D: Residual Y;(Y_{reco} - Y_{MC})(cm)", 1000, -2, 2};
   CbmQaHist<TH1D> fh2DresidualT {"h2DresidualT", "Trd2D: Residual T;(T_{reco} - T_{MC})(ns)", 100, -1000, 1000};
 
   /// Histogram for PULL Distribution
@@ -127,8 +128,8 @@ private:
   CbmQaHist<TH1D> fh1DpullV {"h1DpullV", "Trd1D: Pull V;(V_{reco} - V_{MC}) / #sigmaV_{reco}", 100, -5, 5};
   CbmQaHist<TH1D> fh1DpullT {"h1DpullT", "Trd1D: Pull T;(T_{reco} - T_{MC}) / #sigmaT_{reco}", 100, -5, 5};
 
-  CbmQaHist<TH1D> fh2DpullX {"h2DpullX", "Trd2D: Pull X;(X_{reco} - X_{MC}) / #sigmaX_{reco}", 100, -5, 5};
-  CbmQaHist<TH1D> fh2DpullY {"h2DpullY", "Trd2D: Pull Y;(Y_{reco} - Y_{MC}) / #sigmaY_{reco}", 100, -5, 5};
+  CbmQaHist<TH1D> fh2DpullX {"h2DpullX", "Trd2D: Pull X;(X_{reco} - X_{MC}) / #sigmaX_{reco}", 1000, -5, 5};
+  CbmQaHist<TH1D> fh2DpullY {"h2DpullY", "Trd2D: Pull Y;(Y_{reco} - Y_{MC}) / #sigmaY_{reco}", 1000, -5, 5};
   CbmQaHist<TH1D> fh2DpullT {"h2DpullT", "Trd2D: Pull T;(T_{reco} - T_{MC}) / #sigmaT_{reco}", 100, -5, 5};
 
   /// List of the above histogramms
diff --git a/reco/detectors/trd/CMakeLists.txt b/reco/detectors/trd/CMakeLists.txt
index 7eed7e333f..87f1dd0b5c 100644
--- a/reco/detectors/trd/CMakeLists.txt
+++ b/reco/detectors/trd/CMakeLists.txt
@@ -5,6 +5,7 @@
 Set(INCLUDE_DIRECTORIES
   ${CMAKE_CURRENT_SOURCE_DIR}
   ${CMAKE_CURRENT_SOURCE_DIR}/qa
+  ${CMAKE_CURRENT_SOURCE_DIR}/qa/data
   ${CMAKE_CURRENT_SOURCE_DIR}/pid
   ${CMAKE_CURRENT_SOURCE_DIR}/rawToDigiMethods
   ${CMAKE_CURRENT_SOURCE_DIR}/unpack
@@ -74,6 +75,8 @@ qa/CbmTrdQa.cxx
 qa/CbmTrdRecoQa.cxx
 qa/CbmTrdTracksPidQa.cxx
 
+qa/data/CbmTrdHitMC.cxx
+
 pid/CbmTrdElectronsTrainAnn.cxx
 pid/CbmTrdSetTracksPidWkn.cxx   
 pid/CbmTrdSetTracksPidModWkn.cxx  
diff --git a/reco/detectors/trd/CbmTrdRecoLinkDef.h b/reco/detectors/trd/CbmTrdRecoLinkDef.h
index 122fb9cdcc..3c0121a4ad 100644
--- a/reco/detectors/trd/CbmTrdRecoLinkDef.h
+++ b/reco/detectors/trd/CbmTrdRecoLinkDef.h
@@ -27,6 +27,7 @@
 #pragma link C++ class CbmTrdQa + ;
 #pragma link C++ class CbmTrdRecoQa + ;
 #pragma link C++ class CbmTrdTracksPidQa + ;
+#pragma link C++ class CbmTrdHitMC + ;
 
 #pragma link C++ class std::vector<std::pair<unsigned long, unsigned long>> + ;
 #pragma link C++ class CbmTrdUnpackAlgoBaseR + ;
diff --git a/reco/detectors/trd/qa/data/CbmTrdHitMC.cxx b/reco/detectors/trd/qa/data/CbmTrdHitMC.cxx
new file mode 100644
index 0000000000..48406d78e6
--- /dev/null
+++ b/reco/detectors/trd/qa/data/CbmTrdHitMC.cxx
@@ -0,0 +1,66 @@
+/* Copyright (C) 2018-2022 Horia Hulubei National Institute of Physics and Nuclear Engineering, Bucharest
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Alexandru Bercuci [committer] */
+
+#include "CbmTrdHitMC.h"
+
+#include <TVector3.h>
+
+//_____________________________________________________________________
+CbmTrdHitMC::CbmTrdHitMC() : CbmTrdHit() {}
+
+//_____________________________________________________________________
+CbmTrdHitMC::CbmTrdHitMC(const CbmTrdHit& h) : CbmTrdHit(h) {}
+
+//_____________________________________________________________________
+CbmTrdHitMC::~CbmTrdHitMC() {}
+
+//_____________________________________________________________________
+size_t CbmTrdHitMC::AddPoint(const CbmTrdPoint* p, double t, double m)
+{
+  fTrdPoints.push_back(std::make_tuple(CbmTrdPoint(*p), t, m));
+  return fTrdPoints.size();
+}
+
+//_____________________________________________________________________
+const CbmTrdPoint* CbmTrdHitMC::GetPoint(uint idx) const
+{
+  if (idx >= fTrdPoints.size()) return nullptr;
+  return &std::get<0>(fTrdPoints[idx]);
+}
+
+//_____________________________________________________________________
+double CbmTrdHitMC::GetDx() const
+{
+  const CbmTrdPoint* p(nullptr);
+  if (!(p = GetPoint())) return -999;
+  double dz(GetZ() - p->GetZ()), x(p->GetX() + dz * p->GetPx() / p->GetPz());
+  return GetX() - x;
+}
+
+//_____________________________________________________________________
+double CbmTrdHitMC::GetDy() const
+{
+  const CbmTrdPoint* p(nullptr);
+  if (!(p = GetPoint())) return -999;
+  double dz(GetZ() - p->GetZ()), y(p->GetY() + dz * p->GetPy() / p->GetPz());
+  return GetY() - y;
+}
+
+//_____________________________________________________________________
+double CbmTrdHitMC::GetDt() const
+{
+  constexpr double speedOfLight = 29.979246;  // cm/ns
+  const CbmTrdPoint* p(nullptr);
+  if (!(p = GetPoint())) return -999;
+
+  double t0(std::get<1>(fTrdPoints[0])), mass(std::get<2>(fTrdPoints[0]));
+  double dz(GetZ() - p->GetZ()), t(t0 + p->GetTime());
+
+  TVector3 mom3;
+  p->Momentum(mom3);
+  t += dz / (p->GetPz() * speedOfLight) * sqrt(mass * mass + mom3.Mag2());
+  return GetTime() - t;
+}
+
+ClassImp(CbmTrdHitMC)
diff --git a/reco/detectors/trd/qa/data/CbmTrdHitMC.h b/reco/detectors/trd/qa/data/CbmTrdHitMC.h
new file mode 100644
index 0000000000..015b795d2b
--- /dev/null
+++ b/reco/detectors/trd/qa/data/CbmTrdHitMC.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2018-2022 Horia Hulubei National Institute of Physics and Nuclear Engineering, Bucharest
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Alexandru Bercuci [committer] */
+
+#ifndef CBMTRDHITMC_H
+#define CBMTRDHITMC_H
+
+#include "CbmTrdHit.h"
+#include "CbmTrdPoint.h"
+
+#include <vector>  // for vector
+
+/** \class CbmTrdHitMC
+ * \brief  TRD hit to MC point correlation class
+ * \author Alexandru Bercuci <abercuci@niham.nipne.ro>
+ * \date 02.05.2022
+ * 
+ * The class
+ */
+
+class CbmTrdHitMC : public CbmTrdHit {
+public:
+  /** \brief Default constructor.*/
+  CbmTrdHitMC();
+  /** \brief Standard constructor.*/
+  CbmTrdHitMC(const CbmTrdHit& hit);
+  /** \brief Destructor. */
+  virtual ~CbmTrdHitMC();
+
+  /** \brief Add MC points to the hit. The first time this function is called is for the best matched MC point
+   * \param p: pointer to the point being added 
+   * \param t: time of the event to which the point belongs  
+   * \param m: mass of the particle producing the point  
+   * \return the number of points in the list 
+   */
+  size_t AddPoint(const CbmTrdPoint* p, double t, double m);
+
+  /** \brief Retrieve a MC point
+   * \param idx index of point being requested. by default the best fit is returned. 
+   */
+  const CbmTrdPoint* GetPoint(uint idx = 0) const;
+
+  /** \brief Calculate residuals in the bending plane.*/
+  double GetDx() const;
+  /** \brief Calculate residuals for the azimuth direction.*/
+  double GetDy() const;
+  /** \brief Calculate residuals for time.*/
+  double GetDt() const;
+
+private:
+  /** \brief Copy Constructor.*/
+  CbmTrdHitMC(const CbmTrdHitMC&) = default;
+  /** \brief Assignment operator.*/
+  CbmTrdHitMC& operator=(const CbmTrdHitMC&) = default;
+
+  std::vector<std::tuple<CbmTrdPoint, double, double>> fTrdPoints = {};
+  ClassDef(CbmTrdHitMC, 1)  // Hit to MC point data correlation
+};
+
+#endif
-- 
GitLab