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
17#include "Framework/Logger.h"
18#include <ctime>
19#include <cstring>
20#include <algorithm>
21#include <TRandom.h>
22
23using namespace o2::its;
24
25namespace
26{
27
28// Convert trigger IR to ROF index on a given layer using LayerTiming
29int findROFForIR(const o2::InteractionRecord& ir,
30 const o2::InteractionRecord& tfStartIR,
31 const LayerTiming& layerTiming)
32{
33 // Convert IR to BC-from-TF-start, which is the time base expected by LayerTiming.
34 const int64_t bcFromTFStart = ir.differenceInBC(tfStartIR);
35 if (bcFromTFStart < 0) {
36 return -1;
37 }
38 return layerTiming.getROF(static_cast<LayerTiming::BCType>(bcFromTFStart));
39}
40
41template <int NLayers>
42void enableCompatibleROFs(int baseLayer,
43 int baseRof,
44 const typename o2::its::ROFOverlapTable<NLayers>::View& overlapView,
46{
47 sel.setROFEnabled(baseLayer, baseRof);
48 for (int layer = 0; layer < NLayers; ++layer) {
49 if (layer == baseLayer) {
50 continue;
51 }
52 const auto& overlap = overlapView.getOverlap(baseLayer, layer, baseRof);
53 if (overlap.getEntries() > 0) {
54 sel.setROFsEnabled(layer, overlap.getFirstEntry(), overlap.getEntries());
55 }
56 }
57}
58
59template <int NLayers>
60std::vector<int> buildMultiplicityCounts(const std::array<gsl::span<const o2::itsmft::ROFRecord>, NLayers>& rofs,
61 const std::array<gsl::span<const o2::itsmft::CompClusterExt>, NLayers>& clus,
62 bool doStaggering,
63 int multLayer)
64{
65 std::vector<int> multCounts;
66 if (doStaggering) {
67 multCounts.resize(rofs[multLayer].size());
68 for (size_t iRof = 0; iRof < rofs[multLayer].size(); ++iRof) {
69 multCounts[iRof] = rofs[multLayer][iRof].getNEntries();
70 }
71 return multCounts;
72 }
73
74 static const o2::itsmft::ChipMappingITS chipMapping;
75 multCounts.resize(rofs[0].size(), 0);
76 for (size_t iRof = 0; iRof < rofs[0].size(); ++iRof) {
77 for (const auto& cluster : rofs[0][iRof].getROFData(clus[0])) {
78 if (chipMapping.getLayer(cluster.getSensorID()) == multLayer) {
79 ++multCounts[iRof];
80 }
81 }
82 }
83 return multCounts;
84}
85} // namespace
86
87bool FastMultEst::sSeedSet = false;
88
91{
92 if (!sSeedSet && FastMultEstConfig::Instance().cutRandomFraction > 0.f) {
93 sSeedSet = true;
94 if (FastMultEstConfig::Instance().randomSeed > 0) {
95 gRandom->SetSeed(FastMultEstConfig::Instance().randomSeed);
96 } else if (FastMultEstConfig::Instance().randomSeed < 0) {
97 gRandom->SetSeed(std::time(nullptr) % 0xffff);
98 }
99 }
100}
101
104int FastMultEst::countClustersOnLayer(const gsl::span<const o2::itsmft::CompClusterExt>& clusters) const
105{
106 const int targetLayer = std::clamp(FastMultEstConfig::Instance().cutMultClusLayer, 0, NLayers - 1);
107 int count = 0;
108 int lr = FastMultEst::NLayers - 1;
110 for (int i = clusters.size(); i--;) { // profit from clusters being ordered in chip increasing order
111 while (clusters[i].getSensorID() < nchAcc) {
112 assert(lr >= 0);
114 }
115 if (lr == targetLayer) {
116 ++count;
117 }
118 }
119 return count;
120}
121
125{
126 // Single-layer regime: estimate multiplicity from one configured layer only.
127 const auto& conf = FastMultEstConfig::Instance();
128 const int layer = std::clamp(conf.cutMultClusLayer, 0, NLayers - 1);
129 const float acc = conf.accCorr[layer];
130 nLayersUsed = nClusters > 0 ? 1 : 0;
131 noisePerChip = 0.f;
132 chi2 = 0.f;
133 cov[0] = cov[1] = cov[2] = 0.f;
134 if (nLayersUsed == 0 || acc <= 0.f) {
135 mult = -1.f;
136 return -1.f;
137 }
138 mult = nClusters / acc;
139 return mult > 0 ? mult : 0;
140}
141
145{
146 // Single-layer regime with imposed noise subtraction.
147 const auto& conf = FastMultEstConfig::Instance();
148 const int layer = std::clamp(conf.cutMultClusLayer, 0, NLayers - 1);
149 const float acc = conf.accCorr[layer];
150 const float nch = static_cast<float>(o2::itsmft::ChipMappingITS::getNChipsPerLr(layer));
151 nLayersUsed = nClusters > 0 ? 1 : 0;
152 chi2 = 0.f;
153 cov[0] = cov[1] = cov[2] = 0.f;
154 if (nLayersUsed == 0 || acc <= 0.f) {
155 mult = -1.f;
156 return -1.f;
157 }
158 mult = (nClusters - noisePerChip * nch) / acc;
159 return mult;
160}
161
162int FastMultEst::selectROFs(const std::array<gsl::span<const o2::itsmft::ROFRecord>, NLayers>& rofs,
163 const std::array<gsl::span<const o2::itsmft::CompClusterExt>, NLayers>& clus,
164 const gsl::span<const o2::itsmft::PhysTrigger> trig,
165 uint32_t firstTForbit,
166 bool doStaggering,
167 const ROFOverlapTableN::View& overlapView,
168 ROFMaskTableN& sel)
169{
170 const auto& multEstConf = FastMultEstConfig::Instance(); // parameters for mult estimation and cuts
171 const int selectionLayer = multEstConf.isMultCutRequested() ? std::clamp(multEstConf.cutMultClusLayer, 0, NLayers - 1) : overlapView.getClock();
172 const auto multCounts = buildMultiplicityCounts<NLayers>(rofs, clus, doStaggering, selectionLayer);
173 const int selectionRofCount = doStaggering ? static_cast<int>(rofs[selectionLayer].size()) : static_cast<int>(rofs[0].size());
174
175 sel.resetMask();
176 lastRandomSeed = gRandom->GetSeed();
177 const o2::InteractionRecord tfStartIR{0, firstTForbit};
178 // mask ROFs which are not good from the multiplicity selection (if any) POV
179 struct ROFStatus {
180 int entry = 0, priority = 0;
181 };
182 std::vector<ROFStatus> selROFs;
183 selROFs.reserve(selectionRofCount);
184 bool selmult = multEstConf.isMultCutRequested();
185 for (int selectionRof = 0; selectionRof < selectionRofCount; ++selectionRof) {
186 selROFs.emplace_back(selectionRof, (selmult && !multEstConf.isPassingMultCut(process(multCounts[selectionRof]))) ? -1 : 0);
187 }
188 if (!trig.empty() && multEstConf.preferTriggered) {
189 const auto& selectionLayerTiming = overlapView.getLayer(selectionLayer);
190 for (const auto& trigger : trig) {
191 const int selectionRof = findROFForIR(trigger.ir, tfStartIR, selectionLayerTiming);
192 if (selectionRof < 0 || selROFs[selectionRof].priority < 0) {
193 continue;
194 }
195 selROFs[selectionRof].priority++; // increment trigger counter
196 }
197 sort(selROFs.begin(), selROFs.end(), [](const ROFStatus& a, const ROFStatus& b) { return a.priority > b.priority; }); // order in number of triggers, masked will go to the end
198 }
199 int nsel = 0;
200 for (auto& rof : selROFs) {
201 if (rof.priority >= 0 && (multEstConf.cutRandomFraction <= 0.f || (gRandom->Rndm() > multEstConf.cutRandomFraction))) {
202 enableCompatibleROFs<NLayers>(selectionLayer, rof.entry, overlapView, sel);
203 nsel++;
204 }
205 }
206 LOGP(debug, "NSel = {} of {} rofs on layer {} Seeds: before {} after {}", nsel, selectionRofCount, selectionLayer, lastRandomSeed, gRandom->GetSeed());
207 return nsel;
208}
std::ostringstream debug
Fast multiplicity estimator for ITS.
int32_t i
int nClusters
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
static constexpr int getLayer(int chipSW)
GLint GLsizei count
Definition glcorearb.h:399
GLuint entry
Definition glcorearb.h:5735
GLsizeiptr size
Definition glcorearb.h:659
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
int64_t differenceInBC(const InteractionRecord &other) const
FastMultEst()
state of the gRandom before
ROFMaskTable< NLayers > ROFMaskTableN
Definition FastMultEst.h:36
float processNoiseFree(int nClusters)
int countClustersOnLayer(const gsl::span< const o2::itsmft::CompClusterExt > &clusters) const
int selectROFs(const std::array< gsl::span< const o2::itsmft::ROFRecord >, NLayers > &rofs, const std::array< gsl::span< const o2::itsmft::CompClusterExt >, NLayers > &clus, const gsl::span< const o2::itsmft::PhysTrigger > trig, uint32_t firstTForbit, bool doStaggering, const ROFOverlapTableN::View &overlapView, ROFMaskTableN &sel)
float process(int nClusters)
Definition FastMultEst.h:76
int nLayersUsed
retained for compatibility; set to zero in single-layer mode
Definition FastMultEst.h:42
uint32_t lastRandomSeed
number of layers used by estimator (0/1 in single-layer mode)
Definition FastMultEst.h:43
float cov[3]
imposed noise per chip (when enabled by configuration)
Definition FastMultEst.h:40
float noisePerChip
estimated signal clusters multiplicity on the selected multiplicity layer
Definition FastMultEst.h:39
float chi2
retained for compatibility; set to zero in single-layer mode
Definition FastMultEst.h:41
static bool sSeedSet
Definition FastMultEst.h:86
static constexpr int NLayers
Definition FastMultEst.h:34
float processNoiseImposed(int nClusters)
o2::InteractionRecord ir(0, 0)
std::vector< Cluster > clusters