Project
Loading...
Searching...
No Matches
LQND.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
15
16#ifndef O2_TRD_LQND_H
17#define O2_TRD_LQND_H
18
19#include "TGraph.h"
20#include "TRDPID/PIDBase.h"
21#include "DataFormatsTRD/PID.h"
28#include "Framework/Logger.h"
30
31#include <memory>
32#include <vector>
33#include <array>
34#include <string>
35#include <numeric>
36
37namespace o2
38{
39namespace trd
40{
41namespace detail
42{
44template <int nDim>
45class LUT
46{
47 public:
48 LUT() = default;
49 LUT(std::vector<float> p, std::vector<TGraph> l) : mIntervalsP(p), mLUTs(l) {}
50
51 //
52 const TGraph& get(float p, bool isNegative, int iDim = 0) const
53 {
54 auto upper = std::upper_bound(mIntervalsP.begin(), mIntervalsP.end(), p);
55 if (upper == mIntervalsP.end()) {
56 // outside of momentum intervals, should not happen
57 return mLUTs[0];
58 }
59 auto index = std::distance(mIntervalsP.begin(), upper);
60 index += (isNegative) ? 0 : mIntervalsP.size() * nDim;
61 return mLUTs[index + iDim];
62 }
63
64 private:
65 std::vector<float> mIntervalsP;
66 std::vector<TGraph> mLUTs;
67
68 ClassDefNV(LUT, 1);
69};
70} // namespace detail
71
74template <int nDim>
75class LQND : public PIDBase
76{
77 static_assert(nDim == 1 || nDim == 2 || nDim == 3, "Likelihood only for 1/2/3 dimension");
78 using PIDBase::PIDBase;
79
80 public:
81 ~LQND() = default;
82
84 {
85 // retrieve lookup tables (LUTs) from ccdb
86 mLUTs = *(pc.inputs().get<detail::LUT<nDim>*>(Form("lq%ddlut", nDim)));
87 }
88
89 float process(const TrackTRD& trkIn, const o2::globaltracking::RecoContainer& input, bool isTPCTRD) const final
90 {
91 const auto& trkSeed = isTPCTRD ? input.getTPCTracks()[trkIn.getRefGlobalTrackId()].getParamOut() : input.getTPCITSTracks()[trkIn.getRefGlobalTrackId()].getParamOut(); // seeding track
92 auto trk = trkSeed;
93
94 const auto isNegative = std::signbit(trkSeed.getSign()); // positive and negative charged particles are treated differently since ExB effects the charge distributions
95 const auto& trackletsRaw = input.getTRDTracklets();
96 float lei0{1.f}, lei1{1.f}, lei2{1.f}, lpi0{1.f}, lpi1{1.f}, lpi2{1.f}; // likelihood per layer
97 for (int iLayer = 0; iLayer < constants::NLAYER; ++iLayer) {
98 int trkltId = trkIn.getTrackletIndex(iLayer);
99 if (trkltId < 0) { // no tracklet attached
100 continue;
101 }
102 const auto xCalib = input.getTRDCalibratedTracklets()[trkIn.getTrackletIndex(iLayer)].getX();
103 auto bz = o2::base::Propagator::Instance()->getNominalBz();
104 const auto tgl = trk.getTgl();
105 const auto snp = trk.getSnpAt(o2::math_utils::sector2Angle(HelperMethods::getSector(input.getTRDTracklets()[trkIn.getTrackletIndex(iLayer)].getDetector())), xCalib, bz);
106 const auto& trklt = trackletsRaw[trkltId];
107 const auto [q0, q1, q2] = getCharges(trklt, iLayer, trkIn, input, snp, tgl); // correct charges
108 if constexpr (nDim == 1) {
109 auto lut = mLUTs.get(trk.getP(), isNegative);
110 auto ll1{1.f};
111 ll1 = lut.Eval(q0 + q1 + q2);
112 lei0 *= ll1;
113 lpi0 *= (1.f - ll1);
114 } else if (nDim == 2) {
115 auto lut1 = mLUTs.get(trk.getP(), isNegative, 0);
116 auto lut2 = mLUTs.get(trk.getP(), isNegative, 1);
117 auto ll1{1.f};
118 auto ll2{1.f};
119 ll1 = lut1.Eval(q0 + q2);
120 ll2 = lut2.Eval(q1);
121 lei0 *= ll1;
122 lei1 *= ll2;
123 lpi0 *= (1.f - ll1);
124 lpi1 *= (1.f - ll2);
125 } else {
126 auto lut1 = mLUTs.get(trk.getP(), isNegative, 0);
127 auto lut2 = mLUTs.get(trk.getP(), isNegative, 1);
128 auto lut3 = mLUTs.get(trk.getP(), isNegative, 2);
129 auto ll1{1.f};
130 auto ll2{1.f};
131 auto ll3{1.f};
132 ll1 = lut1.Eval(q0);
133 ll2 = lut2.Eval(q1);
134 ll3 = lut3.Eval(q2);
135 lei0 *= ll1;
136 lei1 *= ll2;
137 lei2 *= ll3;
138 lpi0 *= (1.f - ll1);
139 lpi1 *= (1.f - ll2);
140 lpi2 *= (1.f - ll3);
141 }
142 }
143
144 return (lei0 * lei1 * lei2) / (lei0 * lei1 * lei2 + lpi0 * lpi1 * lpi2); // combined likelihood
145 }
146
147 private:
148 detail::LUT<nDim> mLUTs;
149
150 ClassDefNV(LQND, 1);
151};
152
153using LQ1D = LQND<1>;
154using LQ2D = LQND<2>;
155using LQ3D = LQND<3>;
156
157} // namespace trd
158} // namespace o2
159
160#endif
Global TRD definitions and constants.
This file provides the base interface for pid policies.
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:143
float process(const TrackTRD &trkIn, const o2::globaltracking::RecoContainer &input, bool isTPCTRD) const final
Calculate a PID for a given track.
Definition LQND.h:89
void init(o2::framework::ProcessingContext &pc) final
Initialize the policy.
Definition LQND.h:83
~LQND()=default
PIDBase(PIDPolicy policy)
Definition PIDBase.h:52
std::array< float, constants::NCHARGES > getCharges(const Tracklet64 &tracklet, const int layer, const TrackTRD &trk, const o2::globaltracking::RecoContainer &input, float snp, float tgl) const noexcept
Definition PIDBase.cxx:30
Lookup Table class for ccdb upload.
Definition LQND.h:46
const TGraph & get(float p, bool isNegative, int iDim=0) const
Definition LQND.h:52
LUT(std::vector< float > p, std::vector< TGraph > l)
Definition LQND.h:49
GLuint index
Definition glcorearb.h:781
float sector2Angle(int sect)
Definition Utils.h:193
constexpr int NLAYER
the number of layers
Definition Constants.h:27
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
static int getSector(int det)