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 = overlapView.getClock();
172 int multLayer = std::clamp(multEstConf.cutMultClusLayer, 0, NLayers - 1);
173 if (doStaggering && rofs[multLayer].empty()) {
174 LOGP(info, "FastMultEst multiplicity layer {} has no ROFs, falling back to selection layer {}", multLayer, selectionLayer);
175 multLayer = selectionLayer;
176 }
177
178 const auto multCounts = buildMultiplicityCounts<NLayers>(rofs, clus, doStaggering, multLayer);
179 const int selectionRofCount = doStaggering ? static_cast<int>(rofs[selectionLayer].size()) : static_cast<int>(rofs[0].size());
180
181 sel.resetMask();
182 lastRandomSeed = gRandom->GetSeed();
183 const o2::InteractionRecord tfStartIR{0, firstTForbit};
184
185 if (!trig.empty()) {
186 const auto& selectionLayerTiming = overlapView.getLayer(selectionLayer);
187 const auto& multLayerTiming = overlapView.getLayer(multLayer);
188
189 for (const auto& trigger : trig) {
190 const int selectionRof = findROFForIR(trigger.ir, tfStartIR, selectionLayerTiming);
191 if (selectionRof < 0) {
192 continue;
193 }
194 if (multEstConf.cutRandomFraction > 0.f && gRandom->Rndm() < multEstConf.cutRandomFraction) {
195 continue;
196 }
197 if (multEstConf.isMultCutRequested()) {
198 const int triggerMultRof = doStaggering ? findROFForIR(trigger.ir, tfStartIR, multLayerTiming) : selectionRof;
199 if (triggerMultRof < 0 || triggerMultRof >= static_cast<int>(multCounts.size())) {
200 continue;
201 }
202 if (!multEstConf.isPassingMultCut(process(multCounts[triggerMultRof]))) {
203 continue;
204 }
205 }
206 enableCompatibleROFs<NLayers>(selectionLayer, selectionRof, overlapView, sel);
207 }
208 } else {
209 LOGP(info, "FastMultEst received no physics/TRD triggers, falling back to ROF-driven filtering on layer {}", selectionLayer);
210 for (int selectionRof = 0; selectionRof < selectionRofCount; ++selectionRof) {
211 if (multEstConf.isMultCutRequested()) {
212 bool passes = false;
213 if (!doStaggering || selectionLayer == multLayer) {
214 if (selectionRof < static_cast<int>(multCounts.size())) {
215 passes = multEstConf.isPassingMultCut(process(multCounts[selectionRof]));
216 }
217 } else {
218 const auto& overlap = overlapView.getOverlap(selectionLayer, multLayer, selectionRof);
219 for (int rof = overlap.getFirstEntry(); rof < overlap.getEntriesBound(); ++rof) {
220 if (rof < static_cast<int>(multCounts.size())) {
221 if (multEstConf.isPassingMultCut(process(multCounts[rof]))) {
222 passes = true;
223 break;
224 }
225 }
226 }
227 }
228 if (!passes) {
229 continue;
230 }
231 }
232 if (multEstConf.cutRandomFraction > 0.f && gRandom->Rndm() < multEstConf.cutRandomFraction) {
233 continue;
234 }
235 enableCompatibleROFs<NLayers>(selectionLayer, selectionRof, overlapView, sel);
236 }
237 }
238
239 const auto selView = sel.getView();
240 int nsel = 0;
241 for (int irof = 0; irof < selectionRofCount; ++irof) {
242 nsel += selView.isROFEnabled(selectionLayer, irof);
243 }
244
245 if (!trig.empty() && multEstConf.preferTriggered) {
246 LOGP(debug, "FastMultEst preferTriggered is ignored in trigger-driven mask mode");
247 }
248
249 LOGP(debug, "NSel = {} of {} rofs on layer {} Seeds: before {} after {}", nsel, selectionRofCount, selectionLayer, lastRandomSeed, gRandom->GetSeed());
250
251 return nsel;
252}
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
GLsizeiptr size
Definition glcorearb.h:659
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
void empty(int)
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