|
| 1 | +// Copyright 2019-2022 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 | + |
| 12 | +/// \file closePairRejection.h |
| 13 | +/// \brief Definition of ClosePairRejection class |
| 14 | +/// \author Anton Riedel, TU München, anton.riedel@tum.de |
| 15 | + |
| 16 | +#ifndef PWGCF_FEMTO_CORE_CLOSEPAIRREJECTION_H_ |
| 17 | +#define PWGCF_FEMTO_CORE_CLOSEPAIRREJECTION_H_ |
| 18 | + |
| 19 | +#include "PWGCF/Femto/Core/femtoUtils.h" |
| 20 | +#include "PWGCF/Femto/Core/histManager.h" |
| 21 | + |
| 22 | +#include "Framework/HistogramRegistry.h" |
| 23 | + |
| 24 | +#include <array> |
| 25 | +#include <map> |
| 26 | +#include <numeric> |
| 27 | +#include <string> |
| 28 | +#include <vector> |
| 29 | + |
| 30 | +namespace o2::analysis::femto |
| 31 | +{ |
| 32 | +namespace closepairrejection |
| 33 | +{ |
| 34 | +// enum for track histograms |
| 35 | +enum CprHist { |
| 36 | + // kinemtics |
| 37 | + kAverage, |
| 38 | + kRadius0, |
| 39 | + kRadius1, |
| 40 | + kRadius2, |
| 41 | + kRadius3, |
| 42 | + kRadius4, |
| 43 | + kRadius5, |
| 44 | + kRadius6, |
| 45 | + kRadius7, |
| 46 | + kRadius8, |
| 47 | + kCprHistogramLast |
| 48 | +}; |
| 49 | + |
| 50 | +struct ConfCpr : o2::framework::ConfigurableGroup { |
| 51 | + std::string prefix = std::string("ClosePairRejection"); |
| 52 | + o2::framework::Configurable<bool> on{"on", true, "Turn on CPR"}; |
| 53 | + o2::framework::Configurable<float> detaMax{"detaMax", 0.01f, "Maximium deta"}; |
| 54 | + o2::framework::Configurable<float> dphistarMax{"dphistarMax", 0.01f, "Maximum dphistar"}; |
| 55 | + o2::framework::ConfigurableAxis binningDeta{"binningDeta", {{500, -0.5, 0.5}}, "deta"}; |
| 56 | + o2::framework::ConfigurableAxis binningDphistar{"binningDphistar", {{500, -0.5, 0.5}}, "dphi"}; |
| 57 | +}; |
| 58 | + |
| 59 | +// tpc radii for computing phistar |
| 60 | +constexpr int kNradii = 9; |
| 61 | +constexpr std::array<float, kNradii> kTpcRadius = {85., 105., 125., 145., 165., 185., 205., 225., 245.}; |
| 62 | + |
| 63 | +// directory names |
| 64 | +constexpr char PrefixTrackTrackSe[] = "CPR_TrackTrack/SE/"; |
| 65 | +constexpr char PrefixTrackTrackMe[] = "CPR_TrackTrack/ME/"; |
| 66 | +constexpr char PrefixTrackV0Se[] = "CPR_TrackV0/SE/"; |
| 67 | +constexpr char PrefixTrackV0Me[] = "CPR_TrackV0/ME/"; |
| 68 | + |
| 69 | +// must be in sync with enum TrackVariables |
| 70 | +// the enum gives the correct index in the array |
| 71 | +constexpr std::array<histmanager::HistInfo<CprHist>, kCprHistogramLast> HistTable = { |
| 72 | + {{kAverage, o2::framework::kTH2F, "hAverage", "#Delta #eta vs #Delta #phi* (averaged over all radii); #Delta #eta; #Delta #phi*"}, |
| 73 | + {kRadius0, o2::framework::kTH2F, "hRadius0", "Radius 0: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, |
| 74 | + {kRadius1, o2::framework::kTH2F, "hRadius1", "Radius 1: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, |
| 75 | + {kRadius2, o2::framework::kTH2F, "hRadius2", "Radius 2: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, |
| 76 | + {kRadius3, o2::framework::kTH2F, "hRadius3", "Radius 3: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, |
| 77 | + {kRadius4, o2::framework::kTH2F, "hRadius4", "Radius 4: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, |
| 78 | + {kRadius5, o2::framework::kTH2F, "hRadius5", "Radius 5: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, |
| 79 | + {kRadius6, o2::framework::kTH2F, "hRadius6", "Radius 6: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, |
| 80 | + {kRadius7, o2::framework::kTH2F, "hRadius7", "Radius 7: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, |
| 81 | + {kRadius8, o2::framework::kTH2F, "hRadius8", "Radius 8: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}}}; |
| 82 | + |
| 83 | +template <typename T> |
| 84 | +auto makeCprHistSpecMap(const T& confCpr) |
| 85 | +{ |
| 86 | + return std::map<CprHist, std::vector<framework::AxisSpec>>{ |
| 87 | + {kAverage, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 88 | + {kRadius0, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 89 | + {kRadius1, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 90 | + {kRadius2, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 91 | + {kRadius3, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 92 | + {kRadius4, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 93 | + {kRadius5, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 94 | + {kRadius6, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 95 | + {kRadius7, {confCpr.binningDeta, confCpr.binningDphistar}}, |
| 96 | + {kRadius8, {confCpr.binningDeta, confCpr.binningDphistar}}}; |
| 97 | +}; |
| 98 | + |
| 99 | +template <const char* prefix> |
| 100 | +class CloseTrackRejection |
| 101 | +{ |
| 102 | + public: |
| 103 | + CloseTrackRejection() = default; |
| 104 | + virtual ~CloseTrackRejection() = default; |
| 105 | + |
| 106 | + void init(o2::framework::HistogramRegistry* registry, std::map<CprHist, std::vector<o2::framework::AxisSpec>>& specs, float detaMax, float dphistarMax, int chargeTrack1, int chargeTrack2) |
| 107 | + { |
| 108 | + mDetaMax = detaMax; |
| 109 | + mDphistarMax = dphistarMax; |
| 110 | + |
| 111 | + if (mDetaMax < o2::constants::math::Epsilon || mDphistarMax < o2::constants::math::Epsilon) { |
| 112 | + LOG(fatal) << "Either DetaMax or DphistarMax are 0 or negative. Either turn off CPR or specify reasonable values. Breaking ..."; |
| 113 | + } |
| 114 | + mChargeTrack1 = chargeTrack1; |
| 115 | + mChargeTrack2 = chargeTrack2; |
| 116 | + |
| 117 | + if (utils::sign(mChargeTrack1) != utils::sign(mChargeTrack2)) { |
| 118 | + LOG(warn) << "CPR is truned on for tracks with opposite charge. Is this intended?"; |
| 119 | + } |
| 120 | + |
| 121 | + mHistogramRegistry = registry; |
| 122 | + |
| 123 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kAverage, HistTable), GetHistDesc(kAverage, HistTable), GetHistType(kAverage, HistTable), {specs.at(kAverage)}); |
| 124 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius0, HistTable), GetHistDesc(kRadius0, HistTable), GetHistType(kRadius0, HistTable), {specs.at(kRadius0)}); |
| 125 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius1, HistTable), GetHistDesc(kRadius1, HistTable), GetHistType(kRadius1, HistTable), {specs.at(kRadius1)}); |
| 126 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius2, HistTable), GetHistDesc(kRadius2, HistTable), GetHistType(kRadius2, HistTable), {specs.at(kRadius2)}); |
| 127 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius3, HistTable), GetHistDesc(kRadius3, HistTable), GetHistType(kRadius3, HistTable), {specs.at(kRadius3)}); |
| 128 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius4, HistTable), GetHistDesc(kRadius4, HistTable), GetHistType(kRadius4, HistTable), {specs.at(kRadius4)}); |
| 129 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius5, HistTable), GetHistDesc(kRadius5, HistTable), GetHistType(kRadius5, HistTable), {specs.at(kRadius5)}); |
| 130 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius6, HistTable), GetHistDesc(kRadius6, HistTable), GetHistType(kRadius6, HistTable), {specs.at(kRadius6)}); |
| 131 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius7, HistTable), GetHistDesc(kRadius7, HistTable), GetHistType(kRadius7, HistTable), {specs.at(kRadius7)}); |
| 132 | + mHistogramRegistry->add(std::string(prefix) + GetHistNamev2(kRadius8, HistTable), GetHistDesc(kRadius8, HistTable), GetHistType(kRadius8, HistTable), {specs.at(kRadius8)}); |
| 133 | + } |
| 134 | + |
| 135 | + void setMagField(float magField) { mMagField = magField; } |
| 136 | + |
| 137 | + template <typename T1, typename T2> |
| 138 | + void compute(const T1& track1, const T2& track2) |
| 139 | + { |
| 140 | + // reset values |
| 141 | + mAverageDphistar = 0.f; |
| 142 | + mDeta = 0.f; |
| 143 | + mDphistar.fill(0.f); |
| 144 | + |
| 145 | + mDeta = track1.eta() - track2.eta(); |
| 146 | + for (size_t i = 0; i < kTpcRadius.size(); i++) { |
| 147 | + auto phistar1 = utils::dphistar(mMagField, kTpcRadius[i], mChargeTrack1, track1.pt(), track1.phi()); |
| 148 | + auto phistar2 = utils::dphistar(mMagField, kTpcRadius[i], mChargeTrack2, track2.pt(), track2.phi()); |
| 149 | + if (phistar1 && phistar2) { |
| 150 | + // if the calculation for one phistar fails, keep the default value, which is 0 |
| 151 | + // this makes it more likelier for the pair to be rejected sind the averave will be biased towards lower values |
| 152 | + mDphistar.at(i) = phistar1.value() - phistar2.value(); |
| 153 | + } |
| 154 | + } |
| 155 | + mAverageDphistar = std::accumulate(mDphistar.begin(), mDphistar.end(), 0.f) / mDphistar.size(); |
| 156 | + } |
| 157 | + |
| 158 | + void fill() |
| 159 | + { |
| 160 | + // fill average hist |
| 161 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kAverage, HistTable)), mDeta, mAverageDphistar); |
| 162 | + |
| 163 | + // fill radii hists |
| 164 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius0, HistTable)), mDeta, mDphistar.at(0)); |
| 165 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius1, HistTable)), mDeta, mDphistar.at(1)); |
| 166 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius2, HistTable)), mDeta, mDphistar.at(2)); |
| 167 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius3, HistTable)), mDeta, mDphistar.at(3)); |
| 168 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius4, HistTable)), mDeta, mDphistar.at(4)); |
| 169 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius5, HistTable)), mDeta, mDphistar.at(5)); |
| 170 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius6, HistTable)), mDeta, mDphistar.at(6)); |
| 171 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius7, HistTable)), mDeta, mDphistar.at(7)); |
| 172 | + mHistogramRegistry->fill(HIST(prefix) + HIST(GetHistName(kRadius8, HistTable)), mDeta, mDphistar.at(8)); |
| 173 | + } |
| 174 | + |
| 175 | + bool isClosePair() const |
| 176 | + { |
| 177 | + return std::hypot(mAverageDphistar / mDphistarMax, mDeta / mDetaMax) < 1.f; |
| 178 | + } |
| 179 | + |
| 180 | + private: |
| 181 | + int mChargeTrack1 = 0; |
| 182 | + int mChargeTrack2 = 0; |
| 183 | + float mMagField = 0.f; |
| 184 | + float mAverageDphistar = 0.f; |
| 185 | + float mDeta = 0.f; |
| 186 | + float mDetaMax = 0.f; |
| 187 | + float mDphistarMax = 0.f; |
| 188 | + std::array<float, kNradii> mDphistar = {0.f}; |
| 189 | + |
| 190 | + o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; |
| 191 | +}; |
| 192 | + |
| 193 | +template <const char* prefix> |
| 194 | +class ClosePairRejectionTrackTrack |
| 195 | +{ |
| 196 | + public: |
| 197 | + void init(o2::framework::HistogramRegistry* registry, std::map<CprHist, std::vector<o2::framework::AxisSpec>>& specs, float detaMax, float dphistarMax, int signTrack1, int absChargeTrack1, int signTrack2, int AbsChargeTrack2, bool isActivated) |
| 198 | + { |
| 199 | + mIsActivated = isActivated; |
| 200 | + mCtr.init(registry, specs, detaMax, dphistarMax, signTrack1 * absChargeTrack1, signTrack2 * AbsChargeTrack2); |
| 201 | + } |
| 202 | + |
| 203 | + void setMagField(float magField) { mCtr.setMagField(magField); } |
| 204 | + template <typename T1, typename T2> |
| 205 | + void setPair(const T1& track1, const T2& track2) |
| 206 | + { |
| 207 | + mCtr.compute(track1, track2); |
| 208 | + } |
| 209 | + bool isClosePair() const { return mCtr.isClosePair(); } |
| 210 | + void fill() { mCtr.fill(); } |
| 211 | + bool isActivated() const { return mIsActivated; } |
| 212 | + |
| 213 | + private: |
| 214 | + CloseTrackRejection<prefix> mCtr; |
| 215 | + bool mIsActivated = true; |
| 216 | +}; |
| 217 | + |
| 218 | +template <const char* prefix> |
| 219 | +class ClosePairRejectionTrackV0 // can also be used for any particle type that has pos/neg daughters, like resonances |
| 220 | +{ |
| 221 | + public: |
| 222 | + void init(o2::framework::HistogramRegistry* registry, std::map<CprHist, std::vector<o2::framework::AxisSpec>>& specs, float detaMax, float dphistarMax, int signTrack, int absChargeTrack, bool isActivated) |
| 223 | + { |
| 224 | + mIsActivated = isActivated; |
| 225 | + mSignTrack = signTrack; |
| 226 | + |
| 227 | + // initialize CPR with charge of the track and the same charge for the daughter particle |
| 228 | + // absolute charge of the daughter track will be 1, so we can pass the sign directly |
| 229 | + mCtr.init(registry, specs, detaMax, dphistarMax, signTrack * absChargeTrack, signTrack); |
| 230 | + } |
| 231 | + |
| 232 | + void setMagField(float magField) |
| 233 | + { |
| 234 | + mCtr.setMagField(magField); |
| 235 | + } |
| 236 | + template <typename T1, typename T2, typename T3> |
| 237 | + void setPair(const T1& track, const T2& v0, const T3 /*trackTable*/) |
| 238 | + { |
| 239 | + if (mSignTrack == 1) { |
| 240 | + auto daughter = v0.template posDau_as<T3>(); |
| 241 | + mCtr.compute(track, daughter); |
| 242 | + } else if (mSignTrack == -1) { |
| 243 | + auto daughter = v0.template negDau_as<T3>(); |
| 244 | + mCtr.compute(track, daughter); |
| 245 | + } else { |
| 246 | + LOG(fatal) << "CPR Track-V0: Wrong track sign"; |
| 247 | + } |
| 248 | + } |
| 249 | + |
| 250 | + bool isClosePair() const { return mCtr.isClosePair(); } |
| 251 | + void fill() |
| 252 | + { |
| 253 | + mCtr.fill(); |
| 254 | + } |
| 255 | + bool isActivated() const { return mIsActivated; } |
| 256 | + |
| 257 | + private: |
| 258 | + CloseTrackRejection<prefix> mCtr; |
| 259 | + int mSignTrack = 0; |
| 260 | + bool mIsActivated = true; |
| 261 | +}; |
| 262 | + |
| 263 | +}; // namespace closepairrejection |
| 264 | +}; // namespace o2::analysis::femto |
| 265 | +#endif // PWGCF_FEMTO_CORE_CLOSEPAIRREJECTION_H_ |
0 commit comments