Project
Loading...
Searching...
No Matches
clusterProcessing.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
12#include <algorithm>
13#include <stdexcept>
14#include <cstring>
15#include <vector>
16
19#include "mathUtil.h"
20#include "mathieson.h"
21// Used to analyse the clustering/fitting
22#include "InspectModel.h"
23
24// To keep internal data
25#define CHECK 1
26
27// Type of projection
28// Here add single cathode pads
29// (No intersection with pads
30// in other plane)
31static int includeSinglePads = 1;
32
33namespace o2
34{
35namespace mch
36{
38}
39} // namespace o2
40
41using namespace o2::mch;
42
43// Total number of hits/seeds (number of mathieson)
44// found in the precluster;
45static int nbrOfHits = 0;
46// Storage of the seeds found
47static struct Results_t {
48 std::vector<DataBlock_t> seedList;
49 // mapping pads - groups
50 Groups_t* padToGroups;
51} clusterResults;
52
53// Release memory and reset the seed list
55{
56 for (int i = 0; i < clusterResults.seedList.size(); i++) {
57 delete[] clusterResults.seedList[i].second;
58 }
59 clusterResults.seedList.clear();
60 //
61 deleteShort(clusterResults.padToGroups);
62}
63
65{
66
68 printf("collectGroupMapping nPads=%d\n", nPads);
69 }
70 o2::mch::vectorCopyShort(clusterResults.padToGroups, nPads, padToMGrp);
71}
72
74 const o2::mch::PadIdx_t* mapCath0PadIdxToPadIdx, int nCath0,
75 const o2::mch::Groups_t* cath1Grp,
76 const o2::mch::PadIdx_t* mapCath1PadIdxToPadIdx, int nCath1)
77{
78 clusterResults.padToGroups = new Groups_t[nCath0 + nCath1];
79 if (cath0Grp != nullptr) {
80 for (int p = 0; p < nCath0; p++) {
81 clusterResults.padToGroups[mapCath0PadIdxToPadIdx[p]] = cath0Grp[p];
82 }
83 }
84 if (cath1Grp != nullptr) {
85 for (int p = 0; p < nCath1; p++) {
86 // printf("savePadToCathGroup p[cath1 idx]=%d mapCath1PadIdxToPadIdx[p]=
87 // %d, grp=%d\n", p, mapCath1PadIdxToPadIdx[p], cath1Grp[p]);
88 clusterResults.padToGroups[mapCath1PadIdxToPadIdx[p]] = cath1Grp[p];
89 }
90 }
91}
92
93void o2::mch::collectSeeds(double* theta, o2::mch::Groups_t* thetaToGroup, int K)
94{
95 int sumK = 0;
96
97 // printf("collectSeeds : nbrOfGroups with clusters = %d\n", clusterResults.seedList.size());
98 for (int h = 0; h < clusterResults.seedList.size(); h++) {
99 int k = clusterResults.seedList[h].first;
100 // if (clusterConfig.inspectModelLog >= ClusterConfig.info) {
101 // o2::mch::printTheta(" ",
102 // clusterResults.seedList[h].second,
103 // clusterResults.seedList[h].first);
104 //}
105 o2::mch::copyTheta(clusterResults.seedList[h].second, k,
106 &theta[sumK], K, k);
107 if (thetaToGroup) {
108 o2::mch::vectorSetShort(&thetaToGroup[sumK], h + 1, k);
109 }
110 sumK += k;
111 // if (clusterConfig.inspectModelLog >= ClusterConfig.info) {
112 // printf("collect theta grp=%d, grpSize=%d, adress=%p\n", h, k,
113 // clusterResults.seedList[h].second);
114 //}
115 // delete[] clusterResults.seedList[h].second;
116 }
117 if (sumK > K) {
118 printf("Bad allocation for collectTheta sumK=%d greater than K=%d\n", sumK,
119 K);
120 throw std::overflow_error("Bad Allocation");
121 }
122}
123
124// Extract hits/seeds of a pre-cluster
125int clusterProcess(const double* xyDxyi_, const Mask_t* cathi_,
126 const o2::mch::Mask_t* saturated_, const double* zi_, int chId,
127 int nPads)
128{
129
130 nbrOfHits = 0;
131 // Invalid ??? cleanClusterResults();
132 // if (INSPECTMODEL) {
134 InspectModelChrono(0, false);
135 //}
136
137 const double* xyDxyi;
138 const double* zi;
139 const Mask_t* cathi;
140 const Mask_t* saturated;
141
142 // Large and Noisy clusters
143 double* xyDxyi__;
144 double* zi__;
145 Mask_t* cathi__;
146 Mask_t* saturated__;
147 Mask_t noiseMask[nPads];
148 int nNewPads = 0;
149 double qCutOff = 0.0;
150
151 // Pad filter when there are a too large number of pads
152 if (nPads > clusterConfig.nbrPadLimit) {
153 // Remove noisy event
155 printf("WARNING: remove noisy pads nPads=%d, <q>=%8.1f, min/max q=%8.1f, %8.1f\n",
156 nPads, vectorSum(zi_, nPads) / nPads, vectorMin(zi_, nPads),
157 vectorMax(zi_, nPads));
158 }
159 // Select pads which q > qCutOff
160 double ratioStep = clusterConfig.ratioStepForLargeCluster;
161 double ratio = 1.;
162 double qMax = vectorMax(zi_, nPads);
163 int nPadsTest = nPads;
164
165 while (nPadsTest > clusterConfig.nbrPadLimit) {
166 ratio -= ratioStep;
167 qCutOff = ratio * qMax;
168 vectorBuildMaskGreater(zi_, qCutOff, nPads, noiseMask);
169 nPadsTest = vectorSumShort(noiseMask, nPads);
170 }
171 nNewPads = nPadsTest;
173 printf("WARNING: remove noisy pads qCutOff=%8.1f, nbr of kept Pads=%d/%d\n",
174 qCutOff, nNewPads, nPads);
175 }
176 xyDxyi__ = new double[nNewPads * 4];
177 zi__ = new double[nNewPads];
178 saturated__ = new Mask_t[nNewPads];
179 cathi__ = new Mask_t[nNewPads];
180 //
181 vectorGather(zi_, noiseMask, nPads, zi__);
182 vectorGatherShort(saturated_, noiseMask, nPads, saturated__);
183 vectorGatherShort(cathi_, noiseMask, nPads, cathi__);
184 maskedCopyXYdXY(xyDxyi_, nPads, noiseMask, nPads, xyDxyi__, nNewPads);
185 xyDxyi = xyDxyi__;
186 zi = zi__;
187 cathi = cathi__;
188 saturated = saturated__;
189 nPads = nNewPads;
190 } else {
191 xyDxyi = xyDxyi_;
192 zi = zi_;
193 cathi = cathi_;
194 saturated = saturated_;
195 }
196 // Build a cluster object
197 ClusterPEM cluster(getConstX(xyDxyi, nPads), getConstY(xyDxyi, nPads),
198 getConstDX(xyDxyi, nPads), getConstDY(xyDxyi, nPads), zi,
199 cathi, saturated, chId, nPads);
200
201 // Compute the underlying geometry (cathode plae superposition
202 int nProjPads = cluster.buildProjectedGeometry(includeSinglePads);
203
204 if (nProjPads == 0) {
205 throw std::range_error("No projected pads !!!");
206 }
207
208 // Build geometric groups of pads
209 // which constitute sub-clusters
210 // A sub-cluster can contain several seeds
211 int nGroups = cluster.buildGroupOfPads();
212
213 // Store the mapping in ClusterResults
215 cluster.getNbrOfPads(0), cluster.getCathGroup(1),
216 cluster.getMapCathPadToPad(1), cluster.getNbrOfPads(1));
217
219 // Compute the charge on projected geometry
220 double* qProj = cluster.projectChargeOnProjGeometry(includeSinglePads);
221 // Save the projection with projected pads
222 saveProjectedPads(cluster.getProjectedPads(), qProj);
223 // Save the final groups (or cath-groups)
225 cluster.getNbrOfPads(0), cluster.getCathGroup(1),
226 cluster.getMapCathPadToPad(1), cluster.getNbrOfPads(1));
227 }
228 //
229 // Sub-Cluster loop
230 //
231 int nbrOfProjPadsInTheGroup = 0;
232 // Group allocations
233 // ??? double *xyDxyGrp=nullptr;
234 // ??? double *chGrp=nullptr;
235
236 // EM allocations
237 double* thetaEMFinal = nullptr;
238 int finalK = 0;
239
240 //
241 // Find local maxima (seeds)
242 //
243 for (int g = 1; g <= nGroups; g++) {
244 InspectModelChrono(1, false);
245 //
246 // Exctract the current group
247 //
249 printf("----------------\n");
250 printf("Group %d/%d \n", g, nGroups);
251 printf("----------------\n");
252 }
253 //
254 // Number of seeds in this group
255 int kEM;
256
257 ClusterPEM* subCluster = nullptr;
258 // Extract the sub-cluster
259 // rq : (cluster.getNbrOfPadsInGroup(g) != cluster.getNbrOfPads()) in
260 // the case of a low charge grp has been removed
261 bool originalCluster = (cluster.getNbrOfPadsInGroup(g) == cluster.getNbrOfPads());
262 if ((nGroups == 1) && (originalCluster)) {
263 subCluster = &cluster;
264 } else {
265 subCluster = new ClusterPEM(cluster, g);
266 }
267
268 // To do something ???
269 double meanCharge = 0.5 * (subCluster->getTotalCharge(0) + subCluster->getTotalCharge(1));
270
272 printf("[clusterProcessing] charge= (%7.0f %2.0f) nPads=(%d, %d)\n",
273 subCluster->getTotalCharge(0), subCluster->getTotalCharge(1),
274 subCluster->getNbrOfPads(0), subCluster->getNbrOfPads(1));
275 }
276 int nbrOfPadsInTheGroup = subCluster->getNbrOfPads();
277
278 // Allocation of possible nbr of seeds
279 // (.i.e the nbr of Pads)
280 double thetaL[nbrOfPadsInTheGroup * 5];
281
283 // Compute the local max with laplacian method
284 // Used only to give insights of the cluster
285 subCluster->buildProjectedGeometry(includeSinglePads);
286 kEM =
287 subCluster->findLocalMaxWithBothCathodes(thetaL, nbrOfPadsInTheGroup);
288 double thetaExtra[kEM * 5];
289 copyTheta(thetaL, nbrOfPadsInTheGroup, thetaExtra, kEM, kEM);
290 saveThetaExtraInGroupList(thetaExtra, kEM);
292 printTheta("Theta findLocalMaxWithBothCathodes", meanCharge, thetaExtra, kEM);
293 }
294 }
295 // Add null pads in the neighboring of the sub-cluster
296 // ???
297 subCluster->addBoundaryPads();
298 //
299 // Search for seeds on this sub-cluster
300 kEM = subCluster->findLocalMaxWithPEM(thetaL, nbrOfPadsInTheGroup);
301 if (kEM != 0) {
302 double thetaEM[kEM * 5];
303 copyTheta(thetaL, nbrOfPadsInTheGroup, thetaEM, kEM, kEM);
304
306 printf("[clusterProcessing] Find %2d PEM local maxima : \n", kEM);
307 printTheta("ThetaEM", meanCharge, thetaEM, kEM);
308 }
309
310 //
311 // EM
312 //
313 // ??? double *projXc = getX( xyDxyGrp, nbrOfProjPadsInTheGroup);
314 // ??? double *projYc = getY( xyDxyGrp, nbrOfProjPadsInTheGroup);
315 /*
316 if (VERBOSE > 1) {
317 printf("projPads in the group=%d, Xmin/max = %f %f, min/max = %f %f\n",
318 g, vectorMin( projXc, nbrOfProjPadsInTheGroup),vectorMax( projXc,
319 nbrOfProjPadsInTheGroup), vectorMin( projYc, nbrOfProjPadsInTheGroup),
320 vectorMax( projYc, nbrOfProjPadsInTheGroup));
321 }
322 */
324 // Save the seed founds by the EM algorithm
325 saveThetaEMInGroupList(thetaEM, kEM);
326 }
327 InspectModelChrono(1, true);
328
329 //
330 //
331 //
332 // Perform the fitting if the sub-cluster g
333 // is well separated at the 2 planes level (cath0, cath1)
334 // If not the EM result is kept
335 //
336 InspectModelChrono(2, false);
337
338 DataBlock_t newSeeds = subCluster->fit(thetaEM, kEM);
339 finalK = newSeeds.first;
340 nbrOfHits += finalK;
341 //
342 // Store result (hits/seeds)
343 clusterResults.seedList.push_back(newSeeds);
344 //
346 saveThetaFitInGroupList(newSeeds.second, newSeeds.first);
347 }
348 InspectModelChrono(2, true);
349 } else {
350 // No EM seeds
351 finalK = kEM;
352 nbrOfHits += finalK;
353 // Save the result of EM
354 DataBlock_t newSeeds = std::make_pair(finalK, nullptr);
355 clusterResults.seedList.push_back(newSeeds);
356 }
358 printTheta("ThetaFit:", meanCharge, clusterResults.seedList.back().second, clusterResults.seedList.back().first);
359 }
360 // Release pointer for group
361 // deleteDouble( xyDxyGrp );
362 // deleteDouble( chGrp );
363 if ((nGroups != 1) || (!originalCluster)) {
364 delete subCluster;
365 }
366 } // next group
367
368 // Finalise inspectModel
371 }
372 InspectModelChrono(0, true);
373 InspectModelChrono(-1, true);
374
375 if (nNewPads) {
376 delete[] xyDxyi__;
377 delete[] cathi__;
378 delete[] saturated__;
379 delete[] zi__;
380 }
381 return nbrOfHits;
382}
383/*
384} // namespace mch
385} // namespace o2
386*/
Clustering and fifting parameters.
int32_t i
void saveThetaEMInGroupList(const double *thetaEM, int K)
void InspectModelChrono(int type, bool end)
void finalizeInspectModel()
void saveThetaExtraInGroupList(const double *thetaExtra, int K)
void cleanInspectModel()
void savePadToCathGroup(const o2::mch::Groups_t *cath0Grp, const o2::mch::PadIdx_t *mapCath0PadIdxToPadIdx, int nCath0, const o2::mch::Groups_t *cath1Grp, const o2::mch::PadIdx_t *mapCath1PadIdxToPadIdx, int nCath1)
void saveProjectedPads(const o2::mch::Pads *pads, double *qProj)
void saveThetaFitInGroupList(const double *thetaFit, int K)
Class for time synchronization of RawReader instances.
int getNbrOfPads(int c)
Definition ClusterPEM.h:49
int findLocalMaxWithBothCathodes(double *thetaOut, int kMax)
DataBlock_t fit(double *thetaInit, int K)
const Pads * getProjectedPads()
Definition ClusterPEM.h:97
int buildProjectedGeometry(int includeAlonePads)
double * projectChargeOnProjGeometry(int includeAlonePads)
const PadIdx_t * getMapCathPadToPad(int c)
Definition ClusterPEM.h:91
int getNbrOfPadsInGroup(int g)
const Groups_t * getCathGroup(int c)
Definition ClusterPEM.h:78
int findLocalMaxWithPEM(double *thetaL, int nbrOfPadsInTheGroupCath)
double getTotalCharge(int c)
Definition ClusterPEM.h:65
void storeGroupMapping(const o2::mch::Groups_t *cath0Grp, const o2::mch::PadIdx_t *mapCath0PadIdxToPadIdx, int nCath0, const o2::mch::Groups_t *cath1Grp, const o2::mch::PadIdx_t *mapCath1PadIdxToPadIdx, int nCath1)
int clusterProcess(const double *xyDxyi_, const Mask_t *cathi_, const o2::mch::Mask_t *saturated_, const double *zi_, int chId, int nPads)
GLboolean GLboolean g
Definition glcorearb.h:1233
std::pair< int, double * > DataBlock_t
Definition ClusterPEM.h:30
void printTheta(const char *str, double meanCharge, const double *theta, int K)
void collectSeeds(double *theta, o2::mch::Groups_t *thetaToGroup, int K)
const double * getConstDX(const double *xyDxy, int N)
void cleanClusterResults()
void maskedCopyXYdXY(const double *xyDxy, int nxyDxy, const Mask_t *mask, int nMask, double *xyDxyMasked, int nxyDxyMasked)
void copyTheta(const double *theta0, int K0, double *theta, int K1, int K)
const double * getConstDY(const double *xyDxy, int N)
const double * getConstY(const double *xyDxy, int N)
const double * getConstX(const double *xyDxy, int N)
void deleteShort(short *ptr)
Definition mathUtil.h:540
ClusterConfig clusterConfig
void collectGroupMapping(Mask_t *padToMGrp, int nPads)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
@ active
Describe default activation.
ActivateMode inspectModel
@ info
Describes main steps and high level behaviors.
VerboseMode inspectModelLog