Project
Loading...
Searching...
No Matches
FastMultEst.cxx
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
18#include "Framework/Logger.h"
19#include <ctime>
20#include <cstring>
21#include <TRandom.h>
22
23using namespace o2::its;
24
25bool FastMultEst::sSeedSet = false;
26
29{
30 if (!sSeedSet && FastMultEstConfig::Instance().cutRandomFraction > 0.f) {
31 sSeedSet = true;
32 if (FastMultEstConfig::Instance().randomSeed > 0) {
33 gRandom->SetSeed(FastMultEstConfig::Instance().randomSeed);
34 } else if (FastMultEstConfig::Instance().randomSeed < 0) {
35 gRandom->SetSeed(std::time(nullptr) % 0xffff);
36 }
37 }
38}
39
42void FastMultEst::fillNClPerLayer(const gsl::span<const o2::itsmft::CompClusterExt>& clusters)
43{
45 std::memset(&nClPerLayer[0], 0, sizeof(int) * FastMultEst::NLayers);
46 for (int i = clusters.size(); i--;) { // profit from clusters being ordered in chip increasing order
47 while (clusters[i].getSensorID() < nchAcc) {
48 assert(lr >= 0);
50 }
51 nClPerLayer[lr]++;
52 }
53}
54
57float FastMultEst::processNoiseFree(const std::array<int, NLayers> ncl)
58{
59 // we assume that on the used layers the observed number of clusters is defined by the
60 // the noise ~ nu * Nchips and contribution from the signal tracks Ntr*mAccCorr
61 const auto& conf = FastMultEstConfig::Instance();
62
63 float mat[3] = {0}, b[2] = {0};
64 nLayersUsed = 0;
65 for (int il = conf.firstLayer; il <= conf.lastLayer; il++) {
66 if (ncl[il] > 0) {
68 float err2i = 1. / ncl[il];
69 float m2n = nch * err2i;
70 mat[0] += err2i * conf.accCorr[il] * conf.accCorr[il];
71 mat[2] += nch * m2n;
72 mat[1] += conf.accCorr[il] * m2n; // non-diagonal element
73 b[0] += conf.accCorr[il];
74 b[1] += nch;
76 }
77 }
78 mult = noisePerChip = chi2 = -1;
79 float det = mat[0] * mat[2] - mat[1] * mat[1];
80 if (nLayersUsed < 2 || std::abs(det) < 1e-15) {
81 return -1;
82 }
83 float detI = 1. / det;
84 mult = detI * (b[0] * mat[2] - b[1] * mat[1]);
85 noisePerChip = detI * (b[1] * mat[0] - b[0] * mat[1]);
86 cov[0] = mat[2] * detI;
87 cov[2] = mat[0] * detI;
88 cov[1] = -mat[1] * detI;
89 chi2 = 0.;
90 for (int il = conf.firstLayer; il <= conf.lastLayer; il++) {
91 if (ncl[il] > 0) {
93 float diff = mult * conf.accCorr[il] + nch * noisePerChip - ncl[il];
94 chi2 += diff * diff / ncl[il];
95 }
96 }
97 chi2 = nLayersUsed > 2 ? chi2 / (nLayersUsed - 2) : 0.;
98 return mult > 0 ? mult : 0;
99}
100
103float FastMultEst::processNoiseImposed(const std::array<int, NLayers> ncl)
104{
105 // we assume that on the used layers the observed number of clusters is defined by the
106 // the noise ~ nu * Nchips and contribution from the signal tracks Ntr*conf.accCorr
107 //
108 const auto& conf = FastMultEstConfig::Instance();
109 float accSum = 0., accWSum = 0., noiseSum = 0.;
110 nLayersUsed = 0;
111 for (int il = conf.firstLayer; il <= conf.lastLayer; il++) {
112 if (ncl[il] > 0) {
113 float err = 1. / ncl[il];
114 accSum += conf.accCorr[il];
115 accWSum += conf.accCorr[il] * conf.accCorr[il] * err;
116 noiseSum += o2::itsmft::ChipMappingITS::getNChipsPerLr(il) * conf.accCorr[il] * err;
117 nLayersUsed++;
118 }
119 }
120 mult = 0;
121 if (nLayersUsed) {
122 mult = (accSum - noisePerChip * noiseSum) / accWSum;
123 }
124 return mult;
125}
126
127int FastMultEst::selectROFs(const gsl::span<const o2::itsmft::ROFRecord> rofs, const gsl::span<const o2::itsmft::CompClusterExt> clus,
128 const gsl::span<const o2::itsmft::PhysTrigger> trig, std::vector<uint8_t>& sel)
129{
130 int nrof = rofs.size(), nsel = 0;
131 const auto& multEstConf = FastMultEstConfig::Instance(); // parameters for mult estimation and cuts
132 sel.clear();
133 sel.resize(nrof, true); // by default select all
134 lastRandomSeed = gRandom->GetSeed();
135 if (multEstConf.isMultCutRequested()) {
136 for (uint32_t irof = 0; irof < nrof; irof++) {
137 nsel += sel[irof] = multEstConf.isPassingMultCut(process(rofs[irof].getROFData(clus)));
138 }
139 } else {
140 nsel = nrof;
141 }
142 using IdNT = std::pair<int, int>;
143 if (multEstConf.cutRandomFraction > 0.) {
144 int ntrig = trig.size(), currTrig = 0;
145 if (multEstConf.preferTriggered) {
147 std::vector<IdNT> nTrigROF;
148 nTrigROF.reserve(nrof);
149 for (uint32_t irof = 0; irof < nrof; irof++) {
150 if (sel[irof]) {
151 if (nsel && gRandom->Rndm() < multEstConf.cutRandomFraction) {
152 nsel--;
153 }
154 auto irROF = rofs[irof].getBCData();
155 while (currTrig < ntrig && trig[currTrig].ir < irROF) { // triggers are sorted, jump to 1st one not less than current ROF
156 currTrig++;
157 }
158 auto& trof = nTrigROF.emplace_back(irof, 0);
159 irROF += alpParams.roFrameLengthInBC;
160 while (currTrig < ntrig && trig[currTrig].ir < irROF) {
161 trof.second++;
162 currTrig++;
163 }
164 }
165 }
166 if (nsel > 0) {
167 sort(nTrigROF.begin(), nTrigROF.end(), [](const IdNT& a, const IdNT& b) { return a.second > b.second; }); // order in number of triggers
168 auto last = nTrigROF.begin() + nsel;
169 sort(nTrigROF.begin(), last, [](const IdNT& a, const IdNT& b) { return a.first < b.first; }); // order in ROF ID first nsel ROFs
170 }
171 for (int i = nsel; i < int(nTrigROF.size()); i++) { // reject ROFs in the tail
172 sel[nTrigROF[i].first] = false;
173 }
174 } else { // dummy random rejection
175 for (int irof = 0; irof < nrof; irof++) {
176 if (sel[irof]) {
177 float sr = gRandom->Rndm();
178 if (gRandom->Rndm() < multEstConf.cutRandomFraction) {
179 sel[irof] = false;
180 nsel--;
181 }
182 }
183 }
184 }
185 }
186 LOGP(debug, "NSel = {} of {} rofs Seeds: before {} after {}", nsel, nrof, lastRandomSeed, gRandom->GetSeed());
187
188 return nsel;
189}
int32_t i
Fast multiplicity estimator for ITS.
std::ostringstream debug
static constexpr int getNChipsPerLr(int l)
compose FEEid for given stave (ru) relative to layer and link, see documentation in the constructor
static constexpr int getNChips()
number of chips per barrel
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
std::array< int, NLayers > nClPerLayer
state of the gRandom before
Definition FastMultEst.h:43
float processNoiseFree(const std::array< int, NLayers > ncl)
void fillNClPerLayer(const gsl::span< const o2::itsmft::CompClusterExt > &clusters)
float processNoiseImposed(const std::array< int, NLayers > ncl)
uint32_t lastRandomSeed
number of layers actually used
Definition FastMultEst.h:41
int selectROFs(const gsl::span< const o2::itsmft::ROFRecord > rofs, const gsl::span< const o2::itsmft::CompClusterExt > clus, const gsl::span< const o2::itsmft::PhysTrigger > trig, std::vector< uint8_t > &sel)
float cov[3]
estimated or imposed noise per chip
Definition FastMultEst.h:38
float noisePerChip
estimated signal clusters multipliciy at reference (1st?) layer
Definition FastMultEst.h:37
float chi2
covariance matrix of estimation
Definition FastMultEst.h:39
static bool sSeedSet
Definition FastMultEst.h:62
static constexpr int NLayers
Definition FastMultEst.h:34
o2::InteractionRecord ir(0, 0)
std::vector< Cluster > clusters