Skip to content
Snippets Groups Projects
  • Dominik Smith's avatar
    56819b96
    - Added online capable TRD hitfinders (1D and 2D) in cbm::algo. · 56819b96
    Dominik Smith authored and Felix Weiglhofer's avatar Felix Weiglhofer committed
    - Added ROOT-free implementations of CbmTrdCluster and CbmTrdHit.
    - Added class CbmTaskTrdHitFinder as wrapper for new hitfinders.
    - Added class CbmTaskTrdHitFinderParWrite to produce YAML input files.
    - Added example macro trd_hitfinder_run.C in beamtime/mcbm2022 folder to run new hitfinder.
    - Added a required getter function to CbmTrdParModGeo.h.
    - Updated CMakeLists and LinkDef files to enable compilation.
    56819b96
    History
    - Added online capable TRD hitfinders (1D and 2D) in cbm::algo.
    Dominik Smith authored and Felix Weiglhofer's avatar Felix Weiglhofer committed
    - Added ROOT-free implementations of CbmTrdCluster and CbmTrdHit.
    - Added class CbmTaskTrdHitFinder as wrapper for new hitfinders.
    - Added class CbmTaskTrdHitFinderParWrite to produce YAML input files.
    - Added example macro trd_hitfinder_run.C in beamtime/mcbm2022 folder to run new hitfinder.
    - Added a required getter function to CbmTrdParModGeo.h.
    - Updated CMakeLists and LinkDef files to enable compilation.
HitFinder2D.h 8.87 KiB
/* Copyright (C) 2024 Facility for Antiproton and Ion Research in Europe, Darmstadt
   SPDX-License-Identifier: GPL-3.0-only
   Authors: Dominik Smith [committer], Alexandru Bercuci */

#pragma once

#include "CbmTrdDigi.h"
#include "Cluster2D.h"
#include "DigiRec.h"
#include "Hit.h"
#include "HitFinder2DPars.h"
#include "Math/Rotation3D.h"
#include "Math/Vector3Dfwd.h"

#include <cstdint>
#include <tuple>
#include <unordered_map>
#include <vector>

#define NBINSCORRX 50  //! no of bins in the discretized correction LUT
#define NBINSCORRY 4   //! no of bins in the parametrization correction

#define NANODE 9

using std::vector;
class DigiRec;
class CbmTrdParFaspChannel;


namespace cbm::algo::trd
{

  // working representation of a hit on which the reconstruction is performed
  class HitFactory2D {

   public:
    struct signal {
      double s;   //! working copy of signals from cluster
      double se;  //! working copy of signal errors from cluster
      char t;     //! working copy of signal relative timing
      double x;   //! working copy of signal relative positions
      double xe;  //! working copy of signal relative position errors
      signal(double _s, double _se, char _t, double _x, double _xe) : s(_s), se(_se), t(_t), x(_x), xe(_xe) {}
      signal() : s(0), se(0), t(0), x(0), xe(0) {}
    };

    std::vector<signal> fSignal;
    int nCols;

    uint64_t vt0 = 0;  //! start time of current hit [clk]
    uint8_t vcM  = 0;  //! maximum col
    uint8_t vrM  = 0;  //! maximum row
    uint8_t viM  = 0;  //! index of maximum signal in the projection
    uint16_t vyM = 0;  //! bit map for cluster topology classification

    HitFactory2D(int ncols) : nCols(ncols), vt0(0), vcM(0), vrM(0), viM(0), vyM(0) {}

    void reset()
    {
      fSignal.clear();
      vt0 = 0;
      vcM = 0;
      vrM = 0;
      viM = 0;
      vyM = 0;
    }

    bool HasLeftSgn() const { return TESTBIT(vyM, 3); }
    bool HasOvf() const { return TESTBIT(vyM, 12); }
    bool IsBiasX() const { return TESTBIT(vyM, 4); }
    bool IsBiasXleft() const { return TESTBIT(vyM, 5); }
    bool IsBiasXmid() const { return TESTBIT(vyM, 6); }
    bool IsBiasXright() const { return TESTBIT(vyM, 7); }
    bool IsBiasY() const { return TESTBIT(vyM, 8); }
    bool IsBiasYleft() const { return TESTBIT(vyM, 9); }
    bool IsLeftHit() const { return TESTBIT(vyM, 2); }
    bool IsMaxTilt() const { return TESTBIT(vyM, 0); }
    bool IsOpenLeft() const { return (viM % 2 && !IsMaxTilt()) || (!(viM % 2) && IsMaxTilt()); }
    inline bool IsOpenRight() const;
    bool IsSymmHit() const { return TESTBIT(vyM, 1); }
    void SetBiasX(bool set = 1) { set ? SETBIT(vyM, 4) : CLRBIT(vyM, 4); }
    void SetBiasXleft(bool set = 1) { set ? SETBIT(vyM, 5) : CLRBIT(vyM, 5); }
    void SetBiasXmid(bool set = 1) { set ? SETBIT(vyM, 6) : CLRBIT(vyM, 6); }
    void SetBiasXright(bool set = 1) { set ? SETBIT(vyM, 7) : CLRBIT(vyM, 7); }
    void SetBiasY(bool set = 1) { set ? SETBIT(vyM, 8) : CLRBIT(vyM, 8); }
    void SetBiasYleft(bool set = 1) { set ? SETBIT(vyM, 9) : CLRBIT(vyM, 9); }
    void SetBiasYmid(bool set = 1) { set ? SETBIT(vyM, 10) : CLRBIT(vyM, 10); }
    void SetBiasYright(bool set = 1) { set ? SETBIT(vyM, 11) : CLRBIT(vyM, 11); }
    void SetLeftSgn(bool set = 1) { set ? SETBIT(vyM, 3) : CLRBIT(vyM, 3); }
    void SetLeftHit(bool set = 1) { set ? SETBIT(vyM, 2) : CLRBIT(vyM, 2); }
    void SetSymmHit(bool set = 1) { set ? SETBIT(vyM, 1) : CLRBIT(vyM, 1); }
    void SetMaxTilt(bool set = 1) { set ? SETBIT(vyM, 0) : CLRBIT(vyM, 0); }
    void SetOvf(bool set = 1) { set ? SETBIT(vyM, 12) : CLRBIT(vyM, 12); }
    uint16_t GetHitMap() const { return vyM; }

    std::pair<double, double> GetDxDy(const int n0);
    double GetXoffset(int n0 = 0) const;
    double GetYoffset(int n0 = 0) const;

    void RecenterXoffset(double& dx);
    /** \brief Shift graph representation to [-0.5, 0.5]
   * \param[in] dy offset wrt center pad [ph]
   */
    void RecenterYoffset(double& dy);
    /** \brief Hit classification wrt center pad
   * \return hit type : center hit [0]; side hit [1]
   */

    int GetHitClass() const;
    /** \brief Hit classification wrt signal bias
   * \return hit type : center hit [0]; side hit [1]
   */
    int GetHitRcClass(int a0) const;

    double GetXcorr(double dx, int typ, int cls = 0) const;
    /** \brief y position correction based on LUT
   * \param[in] dy offset computed on charge sharing expressed in [ph]
   * \param[in] cls correction class
   * \return correction expresed in [cm]
   */
    double GetYcorr(double dy, int cls = 0) const;
    /** \brief Shift graph representation to [-0.5, 0.5]
   * \param[in] dx offset wrt center pad [pw]
   */

    static float fgCorrXdx;                         //! step of the discretized correction LUT
    static float fgCorrXval[3][NBINSCORRX];         //! discretized correction LUT
    static float fgCorrYval[NBINSCORRY][2];         //! discretized correction params
    static float fgCorrRcXval[2][NBINSCORRX];       //! discretized correction LUT
    static float fgCorrRcXbiasXval[3][NBINSCORRX];  //! discretized correction LUT

    // Nint function copied from TMath until better option is available
    template<typename T>
    inline int Nint(T x) const
    {
      int i;
      if (x >= 0) {
        i = int(x + 0.5);
        if (i & 1 && x + 0.5 == T(i)) i--;
      }
      else {
        i = int(x - 0.5);
        if (i & 1 && x - 0.5 == T(i)) i++;
      }
      return i;
    }
  };


  /** @class HitFinder2D
 ** @brief Cluster finding and hit reconstruction algorithms for the TRD(2D) module.
 ** @author Alexandru Bercucic <abercuci@niham.nipne.ro>
 ** @since 01.02.2019
 ** @date 01.10.2021
 **
 ** Extend the TRD module reconstructor for the particular case of inner TRD-2D modules.
 ** The class is a collection of algorithms to :
 ** - identify time and spatially correlated digis and build clusters
 ** - identify the type of clusters and apply further merging/deconvolution
 ** - apply FEE (channel gain, baseline) and detector (energy gain, maps, etc) calibration
 ** - steer the calculation of hit 4D parameters (x, y, t, E)
 **/

  class HitFinder2D {
   public:
    typedef std::tuple<uint16_t, uint16_t, int, int, size_t> inputType;  //Tuple: chT, chR, tm, row, id

    /** \brief Default constructor.*/
    HitFinder2D() : fHit(0){};
    /** \brief Constructor with placement */
    HitFinder2D(HitFinder2DModPar params);

    virtual ~HitFinder2D(){};

    /** \brief Steering routine for building hits **/
    std::vector<Hit> operator()(std::vector<Cluster2D>* clusters);

    /** \brief Load RAW digis into working array of RECO digis
   * \param[in] din list of RAW digis in increasing order of column no
   * \param[in] cid cluster index in the cluster array
   * \return no of digis loaded
   */

    int LoadDigis(vector<const CbmTrdDigi*>* din, int cid);
    int ProjectDigis(int cid, int cjd = -1);
    /** \brief Implement topologic cuts for hit merging
   * \return index of anode wire wrt to boundary or 0 if check fails
   */
    int CheckMerge(int cid, int cjd);
    /** \brief Algorithm for hit merging
   * \param[in] h hit to be modified by addition of hp.
   * \param[in] a0 anode hypothesis around boundary (see CheckMerge function).
   * \return TRUE if succesful.
   */
    bool MergeHits(Hit* h, int a0);
    bool BuildHit(Hit* h);
    /** \brief x position correction based on LUT
   * \param[in] dx offset computed on charge sharing expressed in [pw]
   * \param[in] typ hit type central pad [0] or edge [1]
   * \param[in] cls correction class x wrt center [0] row-cross [1] row-cross biassed x [2]
   * \return correction expresed in [cm]
   */

    /** \brief Time offset to synchronize TRD2D hits to the rest of detectors
   * \param dt offset in [ns]
   */
    void SetHitTimeOffset(int dt) { fHitTimeOff = dt; }

   protected:
   private:
    HitFinder2D(const HitFinder2D& ref);
    const HitFinder2D& operator=(const HitFinder2D& ref);

    Hit MakeHit(int cId, const Cluster2D* c, std::vector<const CbmTrdDigi*>* digis, size_t nclusters);

    const float fClk = CbmTrdDigi::Clk(CbmTrdDigi::eCbmTrdAsicType::kFASP);

    HitFinder2DModPar fParams;  ///< Parameter container

    /** \brief Addressing ASIC on module based on id
   * \param[in] id module wise ASIC identifier
   * \return ASIC address within experiment
   */
    inline int GetPadRowCol(int address, int& c);

    std::pair<double, double> CorrectPosition(double dx, double dy, const double xcorr);

    void CalibrateHit(Hit* h, const double dx, const double dy, const double edx, const double edy, const double edt,
                      const double time, const double tdrift, const double eloss);

    std::vector<vector<DigiRec*>> fDigis;  //!cluster-wise organized calibrated digi

    int fHitTimeOff = 0;  //! hit time offset for synchronization

    // working representation of a hit on which the reconstruction is performed
    HitFactory2D fHit;

    static Double_t fgDT[3];  //! FASP delay wrt signal
  };


}  // namespace cbm::algo::trd