Project
Loading...
Searching...
No Matches
InspectModel.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
17
18#include <algorithm>
19#include <stdexcept>
20#include <cstring>
21#include <vector>
22
23#include "InspectModel.h"
25#include "mathUtil.h"
26#include "mathieson.h"
27#include "mathiesonFit.h"
28
29/* Inv
30static InspectModel inspectModel={.nbrOfProjPads=0, .projectedPads=0,
31.projGroups=0, .thetaInit=0, .kThetaInit=0, .totalNbrOfSubClusterPads=0,
32.totalNbrOfSubClusterThetaEMFinal=0, .nCathGroups=0, .padToCathGrp=0};
33*/
34
35namespace o2
36{
37namespace mch
38{
39extern ClusterConfig clusterConfig;
40}
41} // namespace o2
42
43static InspectModel inspectModel;
44// Used when several sub-cluster occur in the precluster
45// Append the new hits/clusters in the thetaList of the pre-cluster
46void copyInGroupList(const double* values, int N, int item_size,
47 std::vector<o2::mch::DataBlock_t>& groupList)
48{
49 double* ptr = new double[N * item_size];
50 // memcpy( (void *) ptr, (const void*) values, N*item_size*sizeof(double));
51 o2::mch::vectorCopy(values, N * item_size, ptr);
52 groupList.push_back(std::make_pair(N, ptr));
53}
54
55/* Inv
56void appendInThetaList( const double *values, int N, std::vector< DataBlock_t >
57&groupList) {
58 // double *ptr = new double[N];
59 // memcpy( (void *) ptr, (const void*) theta, N*sizeof(double));
60 groupList.push_back( std::make_pair(N, values));
61}
62*/
63
64void saveThetaEMInGroupList(const double* thetaEM, int K)
65{
66 int element_size = 5;
67 copyInGroupList(thetaEM, K, element_size,
68 inspectModel.subClusterThetaEMFinal);
69}
70
71void saveThetaExtraInGroupList(const double* thetaExtra, int K)
72{
73 int element_size = 5;
74 copyInGroupList(thetaExtra, K, element_size,
75 inspectModel.subClusterThetaExtra);
76}
77
78void saveThetaFitInGroupList(const double* thetaFit, int K)
79{
80 int element_size = 5;
81 copyInGroupList(thetaFit, K, element_size,
82 inspectModel.subClusterThetaFitList);
83}
84
85void collectTheta(double* theta, o2::mch::Groups_t* thetaToGroup, int K)
86{
87 int sumK = 0;
88
90 printf("collectTheta : nbrOfGroups with clusters = %lu\n", inspectModel.subClusterThetaFitList.size());
91 }
92 for (int h = 0; h < inspectModel.subClusterThetaFitList.size(); h++) {
93 int k = inspectModel.subClusterThetaFitList[h].first;
95 o2::mch::printTheta(" ", 1.0,
96 inspectModel.subClusterThetaFitList[h].second,
97 inspectModel.subClusterThetaFitList[h].first);
98 }
99 o2::mch::copyTheta(inspectModel.subClusterThetaFitList[h].second, k,
100 &theta[sumK], K, k);
101 if (thetaToGroup) {
102 o2::mch::vectorSetShort(&thetaToGroup[sumK], h + 1, k);
103 }
104 sumK += k;
106 printf("collect theta grp=%d, grpSize=%d, adress=%p\n", h, k,
107 inspectModel.subClusterThetaFitList[h].second);
108 }
109 delete[] inspectModel.subClusterThetaFitList[h].second;
110 }
111 if (sumK > K) {
112 printf("Bad allocation for collectTheta sumK=%d greater than K=%d\n", sumK,
113 K);
114 throw std::overflow_error("Bad Allocation");
115 }
116 inspectModel.subClusterThetaFitList.clear();
117}
118
119void savePadsOfSubCluster(const double* xyDxy, const double* q, int n)
120{
121 int element_size = 4;
122 copyInGroupList(xyDxy, n, element_size, inspectModel.subClusterPadList);
123 element_size = 1;
124 copyInGroupList(q, n, element_size, inspectModel.subClusterChargeList);
125}
126
128{
129 //
130 for (int i = 0; i < inspectModel.subClusterPadList.size(); i++) {
131 delete[] inspectModel.subClusterPadList[i].second;
132 }
133 inspectModel.subClusterPadList.clear();
134 //
135 for (int i = 0; i < inspectModel.subClusterChargeList.size(); i++) {
136 delete[] inspectModel.subClusterChargeList[i].second;
137 }
138 inspectModel.subClusterChargeList.clear();
139 //
140 for (int i = 0; i < inspectModel.subClusterThetaEMFinal.size(); i++) {
141 delete[] inspectModel.subClusterThetaEMFinal[i].second;
142 }
143 inspectModel.subClusterThetaEMFinal.clear();
144 //
145 for (int i = 0; i < inspectModel.subClusterThetaExtra.size(); i++) {
146 delete[] inspectModel.subClusterThetaExtra[i].second;
147 }
148 inspectModel.subClusterThetaExtra.clear();
149 //
150 for (int i = 0; i < inspectModel.subClusterThetaFitList.size(); i++) {
151 delete[] inspectModel.subClusterThetaFitList[i].second;
152 }
153 inspectModel.subClusterThetaFitList.clear();
154 //
155 if (inspectModel.projectedPads != nullptr) {
156 delete[] inspectModel.projectedPads;
157 inspectModel.projectedPads = nullptr;
158 }
159 if (inspectModel.qProj != nullptr) {
160 delete[] inspectModel.qProj;
161 inspectModel.qProj = nullptr;
162 }
163 if (inspectModel.projGroups != nullptr) {
164 delete[] inspectModel.projGroups;
165 inspectModel.projGroups = nullptr;
166 }
167 if (inspectModel.thetaInit != nullptr) {
168 delete[] inspectModel.thetaInit;
169 inspectModel.thetaInit = nullptr;
170 }
171 //
172 inspectModel.totalNbrOfSubClusterPads = 0;
173 inspectModel.totalNbrOfSubClusterThetaEMFinal = 0;
174 inspectModel.totalNbrOfSubClusterThetaExtra = 0;
175
176 cleanPixels();
177 // Cath group
178 delete[] inspectModel.padToCathGrp;
179 inspectModel.padToCathGrp = nullptr;
180 inspectModel.nCathGroups = 0;
181
182 // Timing
183 for (int i = 0; i < 4; i++) {
184 inspectModel.duration[i] = 0;
185 }
186}
187
189{
190 int sumN = 0;
191 for (int h = 0; h < inspectModel.subClusterPadList.size(); h++) {
192 int n = inspectModel.subClusterPadList[h].first;
193 sumN += n;
194 }
195 inspectModel.totalNbrOfSubClusterPads = sumN;
196 //
197 int sumK = 0;
198 for (int h = 0; h < inspectModel.subClusterThetaEMFinal.size(); h++) {
199 int k = inspectModel.subClusterThetaEMFinal[h].first;
200 sumK += k;
201 }
202 inspectModel.totalNbrOfSubClusterThetaEMFinal = sumK;
203 //
204 sumK = 0;
205 for (int h = 0; h < inspectModel.subClusterThetaExtra.size(); h++) {
206 int k = inspectModel.subClusterThetaExtra[h].first;
207 sumK += k;
208 }
209 inspectModel.totalNbrOfSubClusterThetaExtra = sumK;
210}
211
212int getNbrOfProjPads() { return inspectModel.nbrOfProjPads; }
213
214int getNbrOfPadsInGroups() { return inspectModel.totalNbrOfSubClusterPads; }
215
217{
218 return inspectModel.totalNbrOfSubClusterThetaEMFinal;
219}
220
222
223void saveProjectedPads(const o2::mch::Pads* pads, double* qProj)
224{
225 int nbrOfProjPads = pads->getNbrOfPads();
226 inspectModel.nbrOfProjPads = nbrOfProjPads;
227 inspectModel.projectedPads = new double[nbrOfProjPads * 4];
228 o2::mch::vectorCopy(pads->getX(), nbrOfProjPads,
229 &inspectModel.projectedPads[0]);
230 o2::mch::vectorCopy(pads->getY(), nbrOfProjPads,
231 &inspectModel.projectedPads[1 * nbrOfProjPads]);
232 o2::mch::vectorCopy(pads->getDX(), nbrOfProjPads,
233 &inspectModel.projectedPads[2 * nbrOfProjPads]);
234 o2::mch::vectorCopy(pads->getDY(), nbrOfProjPads,
235 &inspectModel.projectedPads[3 * nbrOfProjPads]);
236 inspectModel.qProj = qProj;
237}
238
239void collectProjectedPads(double* xyDxy, double* chA, double* chB)
240{
241
242 int nbrOfProjPads = inspectModel.nbrOfProjPads;
243 for (int i = 0; i < 4; i++) {
244 for (int k = 0; k < nbrOfProjPads; k++) {
245 xyDxy[i * nbrOfProjPads + k] =
246 inspectModel.projectedPads[i * nbrOfProjPads + k];
247 }
248 }
249 for (int k = 0; k < nbrOfProjPads; k++) {
250 chA[k] = inspectModel.qProj[k];
251 }
252 for (int k = 0; k < nbrOfProjPads; k++) {
253 chB[k] = inspectModel.qProj[k];
254 }
255 // printf("collectProjectedPads nbrOfProjPads=%d\n", nbrOfProjPads);
256 // o2::mch::vectorPrint( " qProj=", chA, nbrOfProjPads);
257}
258
259void saveProjPadToGroups(o2::mch::Groups_t* projPadToGrp, int N)
260{
261 inspectModel.projGroups = new o2::mch::Groups_t[N];
262 o2::mch::vectorCopyShort(projPadToGrp, N, inspectModel.projGroups);
263}
264
266{
267 int N = inspectModel.nbrOfProjPads;
268 o2::mch::vectorCopyShort(inspectModel.projGroups, N, projPadToGrp);
269 return o2::mch::vectorMaxShort(projPadToGrp, N);
270}
271// ???
272// Optim collectXXX can be replaced by getConstPtrXXX
274 const o2::mch::PadIdx_t* mapCath0PadIdxToPadIdx, int nCath0,
275 const o2::mch::Groups_t* cath1Grp,
276 const o2::mch::PadIdx_t* mapCath1PadIdxToPadIdx, int nCath1)
277{
278 inspectModel.padToCathGrp = new o2::mch::Groups_t[nCath0 + nCath1];
279 if (cath0Grp != nullptr) {
280 for (int p = 0; p < nCath0; p++) {
281 inspectModel.padToCathGrp[mapCath0PadIdxToPadIdx[p]] = cath0Grp[p];
282 }
283 }
284 if (cath1Grp != nullptr) {
285 for (int p = 0; p < nCath1; p++) {
286 // printf("savePadToCathGroup p[cath1 idx]=%d mapCath1PadIdxToPadIdx[p]=
287 // %d, grp=%d\n", p, mapCath1PadIdxToPadIdx[p], cath1Grp[p]);
288 inspectModel.padToCathGrp[mapCath1PadIdxToPadIdx[p]] = cath1Grp[p];
289 }
290 }
291}
292
293void collectPadToCathGroup(o2::mch::Mask_t* padToMGrp, int nPads)
294{
296 printf("collectPadToCathGroup nPads=%d\n", nPads);
297 }
298 o2::mch::vectorCopyShort(inspectModel.padToCathGrp, nPads, padToMGrp);
299}
300
302void collectPadsAndCharges(double* xyDxy, double* z, o2::mch::Groups_t* padToGroup,
303 int N)
304{
305 int sumN = 0;
306 for (int h = 0; h < inspectModel.subClusterPadList.size(); h++) {
307 int n = inspectModel.subClusterPadList[h].first;
308 o2::mch::copyXYdXY(inspectModel.subClusterPadList[h].second, n,
309 &xyDxy[sumN], N, n);
310 o2::mch::vectorCopy(inspectModel.subClusterChargeList[h].second, n,
311 &z[sumN]);
312 if (padToGroup) {
313 o2::mch::vectorSetShort(&padToGroup[sumN], h + 1, n);
314 }
315 sumN += n;
316 delete[] inspectModel.subClusterPadList[h].second;
317 delete[] inspectModel.subClusterChargeList[h].second;
318 }
319 if (sumN > N) {
320 printf("Bad allocation for collectTheta sumN=%d greater than N=%d\n", sumN,
321 N);
322 throw std::overflow_error("Bad Allocation");
323 }
324 inspectModel.subClusterPadList.clear();
325 inspectModel.subClusterChargeList.clear();
326 inspectModel.totalNbrOfSubClusterPads = 0;
327}
328
329// ??? Unused
330/*
331void collectLaplacian( double *laplacian, int N) {
332 o2::mch::vectorCopy( inspectModel.laplacian, N, laplacian );
333}
334 */
335
336/* Unused
337void collectResidual( double *residual, int N) {
338 o2::mch::vectorCopy( inspectModel.residualProj, N, residual );
339}
340*/
341
342int getKThetaInit() { return inspectModel.kThetaInit; }
343
344void collectThetaInit(double* thetai, int N)
345{
346 o2::mch::vectorCopy(inspectModel.thetaInit, 5 * N, thetai);
347}
348
349/* Invalid
350void collectThetaFit( double *thetaFit, int K) {
351 int sumK=0;
352 for (int h=0; h < inspectModel.subClusterThetaFitList.size(); h++) {
353 int k = inspectModel.subClusterThetaFitList[h].first;
354 o2::mch::copyTheta( inspectModel.subClusterThetaFitList[h].second, k,
355&thetaFit[sumK], K, k ); sumK += k; delete[]
356inspectModel.subClusterThetaFitList[h].second;
357 }
358 if ( sumK > K) {
359 printf("Bad allocation for collectThetaFitList sumN=%d greater than N=%d\n",
360sumK, K); throw std::overflow_error("Bad Allocation");
361 }
362 inspectModel.subClusterThetaFitList.clear();
363 // ??? inspectModel.totalNbrOfSubClusterThetaEMFinal = 0;
364}
365*/
366
367void collectThetaEMFinal(double* thetaEM, int K)
368{
369 int sumK = 0;
370 for (int h = 0; h < inspectModel.subClusterThetaEMFinal.size(); h++) {
371 int k = inspectModel.subClusterThetaEMFinal[h].first;
372 o2::mch::copyTheta(inspectModel.subClusterThetaEMFinal[h].second, k,
373 &thetaEM[sumK], K, k);
374 sumK += k;
375 delete[] inspectModel.subClusterThetaEMFinal[h].second;
376 }
377 if (sumK > K) {
378 printf("Bad allocation for collectThetaEMFinal sumN=%d greater than N=%d\n",
379 sumK, K);
380 throw std::overflow_error("Bad Allocation");
381 }
382 inspectModel.subClusterThetaEMFinal.clear();
383 inspectModel.totalNbrOfSubClusterThetaEMFinal = 0;
384}
385
386void collectThetaExtra(double* thetaExtra, int K)
387{
388 int sumK = 0;
389 for (int h = 0; h < inspectModel.subClusterThetaExtra.size(); h++) {
390 int k = inspectModel.subClusterThetaExtra[h].first;
391 o2::mch::copyTheta(inspectModel.subClusterThetaExtra[h].second, k,
392 &thetaExtra[sumK], K, k);
393 sumK += k;
394 delete[] inspectModel.subClusterThetaExtra[h].second;
395 }
396 if (sumK > K) {
397 printf("Bad allocation for collectThetaEMFinal sumN=%d greater than N=%d\n",
398 sumK, K);
399 throw std::overflow_error("Bad Allocation");
400 }
401 inspectModel.subClusterThetaExtra.clear();
402 inspectModel.totalNbrOfSubClusterThetaExtra = 0;
403}
404
405// PadProcess
406//
407
409 inspectPadProcess; //={.xyDxyQPixels ={{0,nullptr}, {0,nullptr},
410 //{0,nullptr}, {0,nullptr}}};
411//.laplacian=0, .residualProj=0, .thetaInit=0, .kThetaInit=0,
412// .totalNbrOfSubClusterPads=0, .totalNbrOfSubClusterThetaEMFinal=0,
413// .nCathGroups=0, .padToCathGrp=0};
414
416{
417 for (int i = 0; i < inspectPadProcess.nPixelStorage; i++) {
418 int G = inspectPadProcess.xyDxyQPixels[i].size();
419 for (int g = 0; g < G; g++) {
420 if (inspectPadProcess.xyDxyQPixels[i][g].first != 0) {
421 delete[] inspectPadProcess.xyDxyQPixels[i][g].second;
422 }
423 inspectPadProcess.xyDxyQPixels[i][g].first = 0;
424 }
425 inspectPadProcess.xyDxyQPixels[i].clear();
426 }
427}
428
429int collectPixels(int which, int N, double* xyDxy, double* q)
430{
431 // which : select the pixel data
432 // N : if N = 0, return the nbr of Pixels
433 // xyDxy : 4N allocated array
434 // q : N allocated array
435
436 int nSrc = 0;
437 const double* xyDxySrc;
438 const double* qSrc;
439 int G = inspectPadProcess.xyDxyQPixels[which].size();
440
441 for (int g = 0; g < G; g++) {
442 nSrc += inspectPadProcess.xyDxyQPixels[which][g].first;
443 }
444 if (N != nSrc) {
445 N = 0;
446 }
447
448 if (N != 0) {
449 int shift = 0;
450 for (int g = 0; g < G; g++) {
451 int n = inspectPadProcess.xyDxyQPixels[which][g].first;
452 xyDxySrc = inspectPadProcess.xyDxyQPixels[which][g].second;
453 qSrc = &xyDxySrc[4 * n];
454 o2::mch::vectorCopy(&xyDxySrc[0 * n], n, &xyDxy[0 * N + shift]);
455 o2::mch::vectorCopy(&xyDxySrc[1 * n], n, &xyDxy[1 * N + shift]);
456 o2::mch::vectorCopy(&xyDxySrc[2 * n], n, &xyDxy[2 * N + shift]);
457 o2::mch::vectorCopy(&xyDxySrc[3 * n], n, &xyDxy[3 * N + shift]);
458 o2::mch::vectorCopy(qSrc, n, &q[shift]);
459 shift += n;
460 }
461 }
462 return nSrc;
463}
464
465void inspectOverWriteQ(int which, const double* qPixels)
466{
467 int G = inspectPadProcess.xyDxyQPixels[which].size();
469 int N = inspectPadProcess.xyDxyQPixels[which][G - 1].first;
470 if (N != 0) {
471 double* xyDxyQ = inspectPadProcess.xyDxyQPixels[which][G - 1].second;
472 double* q = &xyDxyQ[4 * N];
473 o2::mch::vectorCopy(qPixels, N, q);
474 o2::mch::vectorPrint("inspectOverWriteQ ???", q, N);
475 }
476}
477
479{
480 int N = pixels.getNbrOfPads();
481 double* xyDxyQ = new double[5 * N];
482 double* xyDxy = xyDxyQ;
483 double* q = &xyDxyQ[4 * N];
484 o2::mch::vectorCopy(pixels.getX(), N, xyDxy);
485 o2::mch::vectorCopy(pixels.getY(), N, &xyDxy[N]);
486 o2::mch::vectorCopy(pixels.getDX(), N, &xyDxy[2 * N]);
487 o2::mch::vectorCopy(pixels.getDY(), N, &xyDxy[3 * N]);
488 o2::mch::vectorCopy(pixels.getCharges(), N, q);
489 o2::mch::DataBlock_t db = {N, xyDxyQ};
490 inspectPadProcess.xyDxyQPixels[which].push_back(db);
491 // printf("[inspectPadProcess], chanel=%d, nbrGrp=%ld\n", which,
492 // inspectPadProcess.xyDxyQPixels[which].size() );
493}
494
495int getNbrProjectedPads() { return inspectModel.nbrOfProjPads; };
496
498{
499 inspectModel.nbrOfProjPads = n;
500 // inspectModel.maxNbrOfProjPads= n;
501};
502
504{
505 if (type == -1) {
506 // printf("Duration all=%f localMax=%f fitting=%f\n", inspectModel.duration[0], inspectModel.duration[1], inspectModel.duration[2]);
507 return;
508 }
509 if (!end) {
510 // Start
511 inspectModel.startTime[type] = std::chrono::high_resolution_clock::now();
512 } else {
513 std::chrono::time_point<std::chrono::high_resolution_clock> tEnd;
514 tEnd = std::chrono::high_resolution_clock::now();
515 std::chrono::duration<double> duration_ = tEnd - inspectModel.startTime[type];
516 inspectModel.duration[type] += duration_.count();
517 }
518}
519
520/*
521int f_ChargeIntegralMag(const gsl_vector* gslParams, void* dataFit,
522 gsl_vector* residuals)
523{
524 o2::mch::funcDescription_t* dataPtr = (o2::mch::funcDescription_t*)dataFit;
525 int N = dataPtr->N;
526 int K = dataPtr->K;
527 const double* x = dataPtr->x_ptr;
528 const double* y = dataPtr->y_ptr;
529 const double* dx = dataPtr->dx_ptr;
530 const double* dy = dataPtr->dy_ptr;
531 const o2::mch::Mask_t* cath = dataPtr->cath_ptr;
532 const double* zObs = dataPtr->zObs_ptr;
533 o2::mch::Mask_t* notSaturated = dataPtr->notSaturated_ptr;
534 int chamberId = dataPtr->chamberId;
535 // double* cathWeights = dataPtr->cathWeights_ptr;
536 // double* cathMax = dataPtr->cathMax_ptr;
537 // double* zCathTotalCharge = dataPtr->zCathTotalCharge_ptr;
538
539 // Parameters
540 const double* params = gsl_vector_const_ptr(gslParams, 0);
541 // Note:
542 // mux = mu[0:K-1]
543 // muy = mu[K:2K-1]
544 const double* mu = o2::mch::getMuAndW(dataPtr->thetaInit, K);
545 double* w = (double*)&params[0];
546
547 // Set constrain: sum_(w_k) = 1
548 double lastW = 1.0 - o2::mch::vectorSum(w, K - 1);
549 //
550 // Display paramameters (w, mu_x, mu_x
551 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::debug) {
552 printf(" Function evaluation at:\n");
553 for (int k = 0; k < K; k++) {
554 printf(" mu_k[%d] = %g %g \n", k, mu[k], mu[K + k]);
555 }
556 for (int k = 0; k < K - 1; k++) {
557 printf(" w_k[%d] = %g \n", k, w[k]);
558 }
559 // Last W
560 printf(" w_k[%d] = %g \n", K - 1, lastW);
561 }
562
563 // Charge Integral on Pads
564 double z[N];
565 o2::mch::vectorSetZero(z, N);
566 double zTmp[N];
567 //
568 double xyInfSup[4 * N];
569 double* xInf = o2::mch::getXInf(xyInfSup, N);
570 double* xSup = o2::mch::getXSup(xyInfSup, N);
571 double* yInf = o2::mch::getYInf(xyInfSup, N);
572 double* ySup = o2::mch::getYSup(xyInfSup, N);
573
574 // Compute the pads charge considering the
575 // Mathieson set w_k, mu_x, mu_y
576 // TODO: Minor optimization avoid to
577 // compute x[:] - dx[:] i.E use xInf / xSup
578 for (int k = 0; k < K; k++) {
579 // xInf[:] = x[:] - dx[:] - muX[k]
580 o2::mch::vectorAddVector(x, -1.0, dx, N, xInf);
581 o2::mch::vectorAddScalar(xInf, -mu[k], N, xInf);
582 // xSup = xInf + 2.0 * dxy[0]
583 o2::mch::vectorAddVector(xInf, 2.0, dx, N, xSup);
584 // yInf = xy[1] - dxy[1] - mu[k,1]
585 // ySup = yInf + 2.0 * dxy[1]
586 o2::mch::vectorAddVector(y, -1.0, dy, N, yInf);
587 o2::mch::vectorAddScalar(yInf, -mu[K + k], N, yInf);
588 // ySup = yInf + 2.0 * dxy[0]
589 o2::mch::vectorAddVector(yInf, 2.0, dy, N, ySup);
590 //
591 o2::mch::compute2DPadIntegrals(xInf, xSup, yInf, ySup, N, chamberId, zTmp);
592 // Multiply by the weight w[k]
593 double wTmp = (k != K - 1) ? w[k] : lastW;
594 o2::mch::vectorAddVector(z, wTmp, zTmp, N, z);
595 }
596 // ??? vectorPrint("z", z, N);
597 // ??? vectorPrint("zObs", zObs, N);
598 //
599 // Normalisation
600 //
601 double totalCharge = o2::mch::vectorSum(zObs, N);
602 double cathCharge[2] = {0., 0.};
603 o2::mch::Mask_t mask[N];
604 cathCharge[0] = o2::mch::vectorMaskedSum(zObs, mask, N);
605 cathCharge[1] = totalCharge - cathCharge[0];
606 for (int i = 0; i < N; i++) {
607 if (mask[i] == 0) {
608 z[i] = z[i] * cathCharge[0];
609 } else {
610 z[i] = z[i] * cathCharge[1];
611 }
612 }
613 //
614 // Compute residual
615 for (int i = 0; i < N; i++) {
616 // Don't consider saturated pads (notSaturated[i] = 0)
617 double mask = notSaturated[i];
618 if ((notSaturated[i] == 0) && (z[i] < zObs[i])) {
619 // Except those charge < Observed charge
620 mask = 1.0;
621 }
622 //
623 // Residuals with penalization
624 //
625 gsl_vector_set(residuals, i, mask * ((zObs[i] - z[i])));
626 //
627 // Without penalization
628 // gsl_vector_set(residuals, i, mask * (zObs[i] - z[i]) + 0 * wPenal);
629 //
630 // Other studied penalization
631 // gsl_vector_set(residuals, i, (zObs[i] - z[i]) * (1.0 + cathPenal) +
632 // wPenal);
633 }
634 return GSL_SUCCESS;
635}
636
637void printStateMag(int iter, gsl_multifit_fdfsolver* s, int K)
638{
639 printf(" Fitting iter=%3d |f(x)|=%g\n", iter, gsl_blas_dnrm2(s->f));
640 printf(" w:");
641 int k = 0;
642 double sumW = 0;
643 for (; k < K - 1; k++) {
644 double w = gsl_vector_get(s->x, k);
645 sumW += w;
646 printf(" %7.3f", gsl_vector_get(s->x, k));
647 }
648 // Last w : 1.0 - sumW
649 printf(" %7.3f", 1.0 - sumW);
650 printf("\n");
651
652 k = 0;
653 printf(" dw:");
654 for (; k < K - 1; k++) {
655 printf(" % 7.3f", gsl_vector_get(s->dx, k));
656 }
657 printf("\n");
658}
659
660void fitMathiesonMag(const double* xyDxDy, const double* q,
661 const o2::mch::Mask_t* cath, const o2::mch::Mask_t* sat, int chId,
662 double* thetaInit, int K, int N,
663 double* thetaFinal, double* khi2)
664{
665 int status;
666 if (K == 1) {
667 o2::mch::vectorCopy(thetaInit, 5 * K, thetaFinal);
668 return;
669 }
670 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::info) {
671 printf("\n> [fitMathiesonMag] Fitting \n");
672 }
673 //
674 double* muAndWi = o2::mch::getMuAndW(thetaInit, K);
675 //
676 // Check if fitting is possible
677 double* muAndWf = o2::mch::getMuAndW(thetaFinal, K);
678 if (3 * K - 1 > N) {
679 muAndWf[0] = NAN;
680 muAndWf[K] = NAN;
681 muAndWf[2 * K] = NAN;
682 return;
683 }
684
685 o2::mch::funcDescription_t mathiesonData;
686
687 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::detail) {
688 o2::mch::vectorPrintShort(" cath", cath, N);
689 o2::mch::vectorPrint(" q", q, N);
690 }
691
692 mathiesonData.N = N;
693 mathiesonData.K = K;
694 mathiesonData.x_ptr = o2::mch::getConstX(xyDxDy, N);
695 mathiesonData.y_ptr = o2::mch::getConstY(xyDxDy, N);
696 mathiesonData.dx_ptr = o2::mch::getConstDX(xyDxDy, N);
697 mathiesonData.dy_ptr = o2::mch::getConstDY(xyDxDy, N);
698 mathiesonData.cath_ptr = cath;
699 mathiesonData.zObs_ptr = q;
700 o2::mch::Mask_t notSaturated[N];
701 o2::mch::vectorCopyShort(sat, N, notSaturated);
702 o2::mch::vectorNotShort(notSaturated, N, notSaturated);
703 mathiesonData.notSaturated_ptr = notSaturated;
704
705 // Total Charge per cathode plane
706 mathiesonData.cathWeights_ptr = nullptr;
707 mathiesonData.cathMax_ptr = nullptr;
708 mathiesonData.chamberId = chId;
709 mathiesonData.zCathTotalCharge_ptr = nullptr;
710 mathiesonData.verbose = 0;
711 mathiesonData.thetaInit = thetaInit;
712 //
713 // Define Function, jacobian
714 gsl_multifit_function_fdf f;
715 f.f = &f_ChargeIntegralMag;
716 f.df = nullptr;
717 f.fdf = nullptr;
718 f.n = N;
719 f.p = K - 1;
720 f.params = &mathiesonData;
721
722 bool doFit = true;
723 // K test
724 // Sort w
725 int maxIndex[K];
726 for (int k = 0; k < K; k++) {
727 maxIndex[k] = k;
728 }
729 double* w = &muAndWi[2 * K];
730 std::sort(maxIndex, &maxIndex[K],
731 [=](int a, int b) { return (w[a] > w[b]); });
732
733 while (doFit) {
734 // Select the best K's
735 // Copy kTest max
736 double wTest[K];
737 // Mu part
738 for (int k = 0; k < K; k++) {
739 // Respecttively mux, muy, w
740 wTest[k] = muAndWi[maxIndex[k] + 2 * K];
741 }
742 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::detail) {
743 o2::mch::vectorPrint(" Selected w", wTest, K);
744 }
745 mathiesonData.K = K;
746 f.p = K - 1;
747 // Set initial parameters
748 // Inv ??? gsl_vector_view params0 = gsl_vector_view_array(muAndWi, 3 * K -
749 // 1);
750 gsl_vector_view params0 = gsl_vector_view_array(wTest, K - 1);
751
752 // Fitting method
753 gsl_multifit_fdfsolver* s = gsl_multifit_fdfsolver_alloc(
754 gsl_multifit_fdfsolver_lmsder, N, K - 1);
755 // associate the fitting mode, the function, and the starting parameters
756 gsl_multifit_fdfsolver_set(s, &f, &params0.vector);
757
758 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::detail) {
759 printStateMag(-1, s, K);
760 }
761 // double initialResidual = gsl_blas_dnrm2(s->f);
762 double initialResidual = 0.0;
763 // Fitting iteration
764 status = GSL_CONTINUE;
765 double residual = DBL_MAX;
766 double prevResidual = DBL_MAX;
767 double prevW[K - 1];
768 for (int iter = 0; (status == GSL_CONTINUE) && (iter < 50); iter++) {
769 // TODO: to speed if possible
770 for (int k = 0; k < (K - 1); k++) {
771 prevW[k] = gsl_vector_get(s->x, k);
772 }
773 // printf(" Debug Fitting iter=%3d |f(x)|=%g\n", iter,
774 // gsl_blas_dnrm2(s->f));
775 status = gsl_multifit_fdfsolver_iterate(s);
776 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::detail) {
777 printf(" Solver status = %s\n", gsl_strerror(status));
778 printStateMag(iter, s, K);
779 }
780
781 status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4);
782 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::detail) {
783 printf(" Status multifit_test_delta = %d %s\n", status,
784 gsl_strerror(status));
785 }
786 // Residu
787 prevResidual = residual;
788 residual = gsl_blas_dnrm2(s->f);
789 // vectorPrint(" prevtheta", prevTheta, 3*K-1);
790 // vectorPrint(" theta", s->dx->data, 3*K-1);
791 // printf(" prevResidual, residual %f %f\n", prevResidual, residual );
792 if (fabs(prevResidual - residual) < 1.0e-2) {
793 // Stop iteration
794 // Take the previous value of theta
795 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::detail) {
796 printf(" Stop iteration (dResidu~0), prevResidual=%f residual=%f\n",
797 prevResidual, residual);
798 }
799 for (int k = 0; k < (K - 1); k++) {
800 gsl_vector_set(s->x, k, prevW[k]);
801 }
802 status = GSL_SUCCESS;
803 }
804 }
805 double finalResidual = gsl_blas_dnrm2(s->f);
806 bool keepInitialTheta =
807 fabs(finalResidual - initialResidual) / initialResidual < 1.0e-1;
808
809 // Khi2
810 if (khi2 != nullptr) {
811 // Khi2
812 double chi = gsl_blas_dnrm2(s->f);
813 double dof = N - (3 * K - 1);
814 double c = fmax(1.0, chi / sqrt(dof));
815 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::detail) {
816 printf(" K=%d, chi=%f, chisq/dof = %g\n", K, chi * chi,
817 chi * chi / dof);
818 }
819 khi2[0] = chi * chi / dof;
820 }
821
822 // ???? if (keepInitialTheta) {
823 if (0) {
824 // Keep the result of EM (GSL bug when no improvemebt)
825 o2::mch::copyTheta(thetaInit, K, thetaFinal, K, K);
826 } else {
827 // Fitted parameters
828
829 // Mu part
830 for (int k = 0; k < K; k++) {
831 muAndWf[k] = muAndWi[k];
832 muAndWf[k + K] = muAndWi[k + K];
833 }
834 // w part
835 double sumW = 0;
836 for (int k = 0; k < K - 1; k++) {
837 double w = gsl_vector_get(s->x, k);
838 sumW += w;
839 muAndWf[k + 2 * K] = w;
840 }
841 // Last w : 1.0 - sumW
842 muAndWf[3 * K - 1] = 1.0 - sumW;
843 }
844 if (o2::mch::ClusterConfig::fittingLog >= o2::mch::ClusterConfig::detail) {
845 printf(" status parameter error = %s\n", gsl_strerror(status));
846 }
847 gsl_multifit_fdfsolver_free(s);
848 K = K - 1;
849 // doFit = (K < 3) && (K > 0);
850 doFit = false;
851 } // while(doFit)
852 // Release memory
853 //
854 return;
855}
856*/
int32_t i
void collectProjectedPads(double *xyDxy, double *chA, double *chB)
void saveThetaEMInGroupList(const double *thetaEM, int K)
void collectThetaExtra(double *thetaExtra, int K)
void inspectSavePixels(int which, o2::mch::Pads &pixels)
void InspectModelChrono(int type, bool end)
void copyInGroupList(const double *values, int N, int item_size, std::vector< o2::mch::DataBlock_t > &groupList)
int getKThetaInit()
int getNbrProjectedPads()
int collectProjGroups(o2::mch::Groups_t *projPadToGrp)
void finalizeInspectModel()
void saveThetaExtraInGroupList(const double *thetaExtra, int K)
void savePadsOfSubCluster(const double *xyDxy, const double *q, int n)
int getNbrOfPadsInGroups()
void saveProjPadToGroups(o2::mch::Groups_t *projPadToGrp, int N)
void inspectOverWriteQ(int which, const double *qPixels)
void collectPadToCathGroup(o2::mch::Mask_t *padToMGrp, int nPads)
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 collectThetaInit(double *thetai, int N)
int getNbrOfThetaEMFinal()
void cleanPixels()
void collectThetaEMFinal(double *thetaEM, int K)
int collectPixels(int which, int N, double *xyDxy, double *q)
int getNbrOfThetaExtra()
void collectTheta(double *theta, o2::mch::Groups_t *thetaToGroup, int K)
void setNbrProjectedPads(int n)
void collectPadsAndCharges(double *xyDxy, double *z, o2::mch::Groups_t *padToGroup, int N)
???
void saveProjectedPads(const o2::mch::Pads *pads, double *qProj)
void saveThetaFitInGroupList(const double *thetaFit, int K)
int getNbrOfProjPads()
TBranch * ptr
Class for time synchronization of RawReader instances.
const double * getX() const
Definition PadsPEM.h:91
static int getNbrOfPads(const Pads *pads)
Definition PadsPEM.h:63
const double * getDY() const
Definition PadsPEM.h:94
const double * getY() const
Definition PadsPEM.h:92
const double * getDX() const
Definition PadsPEM.h:93
GLdouble n
Definition glcorearb.h:1982
GLuint GLuint end
Definition glcorearb.h:469
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum GLsizei GLsizei GLint * values
Definition glcorearb.h:1576
GLboolean GLboolean g
Definition glcorearb.h:1233
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
Definition glcorearb.h:275
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
std::pair< int, double * > DataBlock_t
Definition ClusterPEM.h:30
void printTheta(const char *str, double meanCharge, const double *theta, int K)
void copyTheta(const double *theta0, int K0, double *theta, int K1, int K)
void vectorPrint(const char *str, const double *x, int K)
Definition mathUtil.cxx:20
void copyXYdXY(const double *xyDxy0, int N0, double *xyDxy, int N1, int N)
ClusterConfig clusterConfig
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::vector< o2::mch::DataBlock_t > xyDxyQPixels[nPixelStorage]
static const int nPixelStorage
double * projectedPads
std::vector< o2::mch::DataBlock_t > subClusterPadList
std::vector< o2::mch::DataBlock_t > subClusterChargeList
double * thetaInit
o2::mch::Groups_t * projGroups
std::vector< o2::mch::DataBlock_t > subClusterThetaEMFinal
int totalNbrOfSubClusterThetaEMFinal
double duration[4]
short * padToCathGrp
double * qProj
int kThetaInit
std::vector< o2::mch::DataBlock_t > subClusterThetaExtra
int totalNbrOfSubClusterPads
std::chrono::time_point< std::chrono::high_resolution_clock > startTime[3]
int totalNbrOfSubClusterThetaExtra
int nCathGroups
int nbrOfProjPads
std::vector< o2::mch::DataBlock_t > subClusterThetaFitList
@ info
Describes main steps and high level behaviors.