41static const int processFitVerbose = 1 + (0 << 2) + (1 << 3) + (1 << 4);
42static const int processFit = 0 + (0 << 2) + (1 << 3) + (1 << 4);
68 for (
i = 0;
i <
m->size1;
i++) {
69 for (
j = 0;
j <
m->size2;
j++) {
70 printf(
"%f\t", gsl_matrix_get(
m,
i,
j));
79 int nPackets = N / 10 + 1;
80 printf(
"%s dim=%d nPackets=%d\n ",
str, N, nPackets);
81 for (
int i = 0;
i < nPackets;
i++) {
82 for (
int k = 0; (k < 10) && ((
i * 10 + k) < N); k++) {
83 printf(
"%f ", gsl_vector_get(
v,
i * 10 + k));
103 gsl_matrix *V, *Sigma_pinv, *U, *A_pinv;
104 gsl_matrix* _tmp_mat =
nullptr;
105 gsl_vector* _tmp_vec;
109 unsigned int n =
A->size1;
110 unsigned int m =
A->size2;
111 bool was_swapped =
false;
116 _tmp_mat = gsl_matrix_alloc(
m,
n);
117 gsl_matrix_transpose_memcpy(_tmp_mat,
A);
125 V = gsl_matrix_alloc(
m,
m);
126 u = gsl_vector_alloc(
m);
127 _tmp_vec = gsl_vector_alloc(
m);
128 gsl_linalg_SV_decomp(
A, V, u, _tmp_vec);
129 gsl_vector_free(_tmp_vec);
132 Sigma_pinv = gsl_matrix_alloc(
m,
n);
133 gsl_matrix_set_zero(Sigma_pinv);
134 cutoff = rcond * gsl_vector_max(u);
136 for (
i = 0;
i <
m; ++
i) {
137 if (gsl_vector_get(u,
i) > cutoff) {
138 x = 1. / gsl_vector_get(u,
i);
142 gsl_matrix_set(Sigma_pinv,
i,
i,
x);
146 U = gsl_matrix_alloc(
n,
n);
147 gsl_matrix_set_zero(U);
149 for (
i = 0;
i <
n; ++
i) {
150 for (
j = 0;
j <
m; ++
j) {
151 gsl_matrix_set(U,
i,
j, gsl_matrix_get(
A,
i,
j));
155 if (_tmp_mat !=
nullptr) {
156 gsl_matrix_free(_tmp_mat);
160 _tmp_mat = gsl_matrix_alloc(
m,
n);
161 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1., V, Sigma_pinv, 0., _tmp_mat);
164 A_pinv = gsl_matrix_alloc(
n,
m);
165 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1., U, _tmp_mat, 0., A_pinv);
167 A_pinv = gsl_matrix_alloc(
m,
n);
168 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1., _tmp_mat, U, 0., A_pinv);
171 gsl_matrix_free(_tmp_mat);
173 gsl_matrix_free(Sigma_pinv);
183 const unsigned int N = 2;
184 const unsigned int M = 3;
187 gsl_matrix*
A = gsl_matrix_alloc(N, M);
190 gsl_matrix_set(
A, 0, 0, 1.);
191 gsl_matrix_set(
A, 0, 1, 3.);
192 gsl_matrix_set(
A, 0, 2, 5.);
193 gsl_matrix_set(
A, 1, 0, 2.);
194 gsl_matrix_set(
A, 1, 1, 4.);
195 gsl_matrix_set(
A, 1, 2, 6.);
197 printf(
"A matrix:\n");
200 printf(
"\nPseudoinverse of A:\n");
204 gsl_matrix_free(A_pinv);
214 singleCathPlaneID = -1;
215 if (pads0 !=
nullptr) {
216 pads[nPlanes] = pads0;
219 singleCathPlaneID = 1;
221 if (pads1 !=
nullptr) {
222 pads[nPlanes] = pads1;
225 singleCathPlaneID = 0;
227 nbrOfCathodePlanes = nPlanes;
231 const double* dy,
const double* q,
const short* cathodes,
232 const short* saturated,
int chId,
int nPads)
236 nbrSaturated = vectorSumShort(saturated, nPads);
238 int nbrCath1 = vectorSumShort(cathodes, nPads);
239 int nbrCath0 = nPads - nbrCath1;
244 mapCathPadIdxToPadIdx[0] =
new PadIdx_t[nbrCath0];
245 pads[0] =
new Pads(
x,
y, dx, dy, q, cathodes, saturated, 0, chId,
246 mapCathPadIdxToPadIdx[0], nPads);
247 singleCathPlaneID = 0;
251 mapCathPadIdxToPadIdx[1] =
new PadIdx_t[nbrCath1];
252 pads[1] =
new Pads(
x,
y, dx, dy, q, cathodes, saturated, 1, chId,
253 mapCathPadIdxToPadIdx[1], nPads);
254 singleCathPlaneID = 1;
258 nbrOfCathodePlanes = nCath;
259 if (nbrOfCathodePlanes == 2) {
260 singleCathPlaneID = -1;
264 projectedPads =
nullptr;
266 projPadToGrp =
nullptr;
269 cathGroup[0] =
nullptr;
270 cathGroup[1] =
nullptr;
277 aloneIPads =
nullptr;
278 aloneJPads =
nullptr;
279 aloneKPads =
nullptr;
283 printf(
"-----------------------------\n");
284 printf(
"Starting CLUSTER PROCESSING\n");
285 printf(
"# cath0=%2d, cath1=%2d\n", nbrCath0, nbrCath1);
286 printf(
"# sum Q0=%7.3g, sum Q1=%7.3g\n",
289 printf(
"# singleCathPlaneID=%2d\n", singleCathPlaneID);
296 chamberId = cluster.chamberId;
297 int nbrCath[2] = {0, 0};
298 nbrCath[0] = (cluster.pads[0]) ? cluster.pads[0]->
getNbrOfPads() : 0;
299 nbrCath[1] = (cluster.pads[1]) ? cluster.pads[1]->
getNbrOfPads() : 0;
303 Mask_t maskGrpCath0[nbrCath[0]];
304 Mask_t maskGrpCath1[nbrCath[1]];
305 Mask_t* maskGrpCath[2] = {maskGrpCath0, maskGrpCath1};
306 int nbrCathPlanes_ = 0;
307 int singleCathPlaneID_ = -1;
308 for (
int c = 0;
c < 2;
c++) {
312 nbrPads = vectorBuildMaskEqualShort(cluster.cathGroup[
c],
g,
320 pads[
c] =
new Pads(*cluster.pads[
c], maskGrpCath[
c]);
322 singleCathPlaneID_ =
c;
325 nbrOfCathodePlanes = nbrCathPlanes_;
326 if (nbrCathPlanes_ != 2) {
327 singleCathPlaneID = singleCathPlaneID_;
336 int nbrOfProjPadsInTheGroup = vectorBuildMaskEqualShort(
337 cluster.projPadToGrp,
g, cluster.projectedPads->
getNbrOfPads(),
339 projectedPads =
new Pads(*cluster.projectedPads, maskProjGrp);
344 for (
int c = 0;
c < 2;
c++) {
345 if (pads[
c] !=
nullptr) {
352 if (projectedPads !=
nullptr) {
353 delete projectedPads;
354 projectedPads =
nullptr;
360 if (mapKToIJ !=
nullptr) {
373 for (
int c = 0;
c < 2;
c++) {
374 if (pads[
c] !=
nullptr) {
388 if (matrix[
i * M +
j] == 1) {
402int ClusterPEM::getIndexByColumns(
const char* matrix,
PadIdx_t N,
PadIdx_t M,
408 if (matrix[
i * M +
j] == 1) {
420int ClusterPEM::checkConsistencyMapKToIJ(
const char* intersectionMatrix,
421 const MapKToIJ_t* mapKToIJ,
425 int N1,
int nbrOfProjPads)
432 for (
PadIdx_t k = 0; k < nbrOfProjPads; k++) {
434 if ((ij.i >= 0) && (ij.j >= 0)) {
435 if (intersectionMatrix[ij.i * N1 + ij.j] != 1) {
436 printf(
"ERROR: no intersection %d %d %d\n", ij.i, ij.j,
437 intersectionMatrix[ij.i * N1 + ij.j]);
438 throw std::overflow_error(
"Divide by zero exception");
443 }
else if (ij.i < 0) {
444 if (aloneJPads[ij.j] != k) {
445 printf(
"ERROR: j-pad should be alone %d %d %d %d\n", ij.i, ij.j,
446 aloneIPads[ij.j], k);
447 throw std::overflow_error(
"Divide by zero exception");
450 }
else if (ij.j < 0) {
451 if (aloneIPads[ij.i] != k) {
452 printf(
"ERROR: i-pad should be alone %d %d %d %d\n", ij.i, ij.j,
453 aloneJPads[ij.j], k);
454 throw std::overflow_error(
"Divide by zero exception");
460 int sum = vectorSumChar(intersectionMatrix, N0 * N1);
462 printf(
"ERROR: nbr of intersection differs %d %d \n",
n,
sum);
463 throw std::overflow_error(
"Divide by zero exception");
467 for (
int i = 0;
i < N0;
i++) {
468 for (
int j = 0;
j < N1;
j++) {
469 int k = mapIJToK[
i * N1 +
j];
472 if ((ij.i !=
i) || (ij.j !=
j)) {
473 throw std::overflow_error(
474 "checkConsistencyMapKToIJ: MapIJToK/MapKToIJ");
475 printf(
"ij.i=%d, ij.j=%d, i=%d, j=%d \n", ij.i, ij.j,
i,
j);
481 for (
PadIdx_t k = 0; k < nbrOfProjPads; k++) {
484 if (aloneJPads[ij.j] != k) {
485 printf(
"i, j, k = %d, %d %d\n", ij.i, ij.j, k);
486 throw std::overflow_error(
487 "checkConsistencyMapKToIJ: MapKToIJ/MapIJToK aloneJPads");
489 }
else if (ij.j < 0) {
490 if (aloneIPads[ij.i] != k) {
491 printf(
"i, j, k = %d, %d %d\n", ij.i, ij.j, k);
492 throw std::overflow_error(
493 "checkConsistencyMapKToIJ: MapKToIJ/MapIJToK aloneIPads");
495 }
else if (mapIJToK[ij.i * N1 + ij.j] != k) {
496 printf(
"i, j, k = %d, %d %d\n", ij.i, ij.j, k);
497 throw std::overflow_error(
"checkConsistencyMapKToIJ: MapKToIJ/MapIJToK");
504void ClusterPEM::computeProjectedPads(
const Pads& pad0InfSup,
505 const Pads& pad1InfSup,
506 int maxNbrProjectedPads,
508 PadIdx_t* aloneKPads,
int includeAlonePads)
515 const double* x0Inf = pad0InfSup.getXInf();
516 const double* y0Inf = pad0InfSup.getYInf();
517 const double* x0Sup = pad0InfSup.getXSup();
518 const double* y0Sup = pad0InfSup.getYSup();
519 const double* x1Inf = pad1InfSup.getXInf();
520 const double* y1Inf = pad1InfSup.getYInf();
521 const double* x1Sup = pad1InfSup.getXSup();
522 const double* y1Sup = pad1InfSup.getYSup();
523 int N0 = pad0InfSup.getNbrOfPads();
524 int N1 = pad1InfSup.getNbrOfPads();
534 double* projX =
new double[maxNbrProjectedPads];
535 double* projY =
new double[maxNbrProjectedPads];
536 double* projDX =
new double[maxNbrProjectedPads];
537 double* projDY =
new double[maxNbrProjectedPads];
541 double countIInterJ, countJInterI;
543 for (
i = 0;
i < N0;
i++) {
545 for (countIInterJ = 0; *ij_ptr != -1; countIInterJ++, ij_ptr++) {
550 l = std::fmax(x0Inf[
i], x1Inf[
j]);
551 r = std::fmin(x0Sup[
i], x1Sup[
j]);
552 b = std::fmax(y0Inf[
i], y1Inf[
j]);
553 t = std::fmin(y0Sup[
i], y1Sup[
j]);
554 projX[k] = (l +
r) * 0.5;
555 projY[k] = (
b + t) * 0.5;
556 projDX[k] = (
r - l) * 0.5;
557 projDY[k] = (t -
b) * 0.5;
560 mapIJToK[
i * N1 +
j] = k;
563 printf(
"newpad %d %d %d %9.3g %9.3g %9.3g %9.3g\n",
i,
j, k, projX[k],
564 projY[k], projDX[k], projDY[k]);
569 if ((countIInterJ == 0) && includeAlonePads) {
574 projX[k] = (l +
r) * 0.5;
575 projY[k] = (
b + t) * 0.5;
576 projDX[k] = (
r - l) * 0.5;
577 projDY[k] = (t -
b) * 0.5;
590 if (includeAlonePads) {
593 for (countJInterI = 0; *ij_ptr != -1; countJInterI++) {
596 if (countJInterI == 0) {
601 projX[k] = (l +
r) * 0.5;
602 projY[k] = (
b + t) * 0.5;
603 projDX[k] = (
r - l) * 0.5;
604 projDY[k] = (t -
b) * 0.5;
620 printf(
"builProjectPads mapIJToK=%p, N0=%d N1=%d\\n", mapIJToK, N0, N1);
621 for (
int i = 0;
i < N0;
i++) {
622 for (
int j = 0;
j < N1;
j++) {
623 if ((mapIJToK[
i * N1 +
j] != -1)) {
624 printf(
" %d inter %d\n",
i,
j);
630 projectedPads =
new Pads(projX, projY, projDX, projDY, chamberId, k);
637 if (nbrOfCathodePlanes == 1) {
647 char intersectionMatrix[N0 * N1];
648 vectorSetZeroChar(intersectionMatrix, N0 * N1);
654 vectorSetInt(mapIJToK, -1, N0 * N1);
660 double xmin, xmax, ymin, ymax;
662 const double* x0Inf = padInfSup0.
getXInf();
663 const double* x0Sup = padInfSup0.
getXSup();
664 const double* y0Inf = padInfSup0.
getYInf();
665 const double* y0Sup = padInfSup0.
getYSup();
666 const double* x1Inf = padInfSup1.
getXInf();
667 const double* x1Sup = padInfSup1.
getXSup();
668 const double* y1Inf = padInfSup1.
getYInf();
669 const double* y1Sup = padInfSup1.
getYSup();
672 xmin = std::fmax(x0Inf[
i], x1Inf[
j]);
673 xmax = std::fmin(x0Sup[
i], x1Sup[
j]);
676 ymin = std::fmax(y0Inf[
i], y1Inf[
j]);
677 ymax = std::fmin(y0Sup[
i], y1Sup[
j]);
679 intersectionMatrix[
i * N1 +
j] = yInter;
693 int maxNbrOfProjPads = vectorSumChar(intersectionMatrix, N0 * N1);
694 int nbrOfSinglePads = 0;
695 if (includeSingleCathodePads) {
698 if (vectorSumRowChar(&intersectionMatrix[
i * N1], N0, N1) == 0) {
704 if (vectorSumColumnChar(&intersectionMatrix[
j], N0, N1) == 0) {
710 maxNbrOfProjPads += nbrOfSinglePads + fmax(N0, N1);
712 printf(
" maxNbrOfProjPads %d\n", maxNbrOfProjPads);
719 IInterJ =
new PadIdx_t[maxNbrOfProjPads];
720 JInterI =
new PadIdx_t[maxNbrOfProjPads];
721 int checkr = getIndexByRow(intersectionMatrix, N0, N1, IInterJ);
722 int checkc = getIndexByColumns(intersectionMatrix, N0, N1, JInterI);
724 if ((checkr > maxNbrOfProjPads) || (checkc > maxNbrOfProjPads)) {
726 "Allocation pb for IInterJ or JInterI: allocated=%d, needed for "
727 "row=%d, for col=%d \n",
728 maxNbrOfProjPads, checkr, checkc);
729 throw std::overflow_error(
"Allocation pb for IInterJ or JInterI");
744 aloneKPads =
new PadIdx_t[maxNbrOfProjPads];
745 vectorSetInt(aloneIPads, -1, N0);
746 vectorSetInt(aloneJPads, -1, N1);
747 vectorSetInt(aloneKPads, -1, maxNbrOfProjPads);
752 computeProjectedPads(padInfSup0, padInfSup1, maxNbrOfProjPads, aloneIPads,
753 aloneJPads, aloneKPads, includeSingleCathodePads);
756 checkConsistencyMapKToIJ(intersectionMatrix, mapKToIJ, mapIJToK, aloneIPads,
763 int thereAreIsolatedPads = 0;
767 printf(
" Neighbors of the projected geometry\n");
772 for (
PadIdx_t k = 0; k < nbrOfProjPads; k++) {
773 if (getTheFirstNeighborOf(projNeighbors, k) == -1) {
775 thereAreIsolatedPads = 1;
777 if ((ij.
i >= 0) && (ij.
j >= 0)) {
779 printf(
" Isolated pad: nul intersection i,j = %d %d\n", ij.
i, ij.
j);
781 intersectionMatrix[ij.
i * N1 + ij.
j] = 0;
783 throw std::overflow_error(
"I/j negative (alone pad)");
788 printf(
"There are isolated pads %d\n", thereAreIsolatedPads);
791 if (thereAreIsolatedPads == 1) {
794 getIndexByRow(intersectionMatrix, N0, N1, IInterJ);
795 getIndexByColumns(intersectionMatrix, N0, N1, JInterI);
799 delete projectedPads;
800 computeProjectedPads(padInfSup0, padInfSup1, maxNbrOfProjPads, aloneIPads,
801 aloneJPads, aloneKPads, includeSingleCathodePads);
811 if (nbrOfCathodePlanes == 1) {
812 Pads* sPads = pads[singleCathPlaneID];
824 double minProj[nbrOfProjPads];
825 double maxProj[nbrOfProjPads];
826 double projCh0[nbrOfProjPads];
827 double projCh1[nbrOfProjPads];
838 for (sumCh1ByRow = 0.0; *ij_ptr != -1; ij_ptr++) {
839 sumCh1ByRow += ch1[*ij_ptr];
841 double ch0_i = ch0[
i];
842 if (sumCh1ByRow != 0.0) {
843 double cst = ch0[
i] / sumCh1ByRow;
844 for (ij_ptr = rowStart; *ij_ptr != -1; ij_ptr++) {
845 projCh0[k] = ch1[*ij_ptr] * cst;
846 minProj[k] = fmin(ch1[*ij_ptr], ch0_i);
847 maxProj[k] = fmax(ch1[*ij_ptr], ch0_i);
853 }
else if (includeAlonePads) {
864 if (includeAlonePads) {
886 for (sumCh0ByCol = 0.0; *ij_ptr != -1; ij_ptr++) {
887 sumCh0ByCol += ch0[*ij_ptr];
889 if (sumCh0ByCol != 0.0) {
890 double cst = ch1[
j] / sumCh0ByCol;
891 for (ij_ptr = colStart; *ij_ptr != -1; ij_ptr++) {
893 k = mapIJToK[
i * N1 +
j];
894 projCh1[k] = ch0[
i] * cst;
899 }
else if (includeAlonePads) {
903 printf(
"ERROR: Alone j-pad with negative index j=%d\n",
j);
912 if (includeAlonePads) {
924 qProj =
new double[nbrOfProjPads];
925 vectorAddVector(projCh0, 1.0, projCh1, nbrOfProjPads, qProj);
926 vectorMultScalar(qProj, 0.5, nbrOfProjPads, qProj);
936 projPadToGrp =
new Groups_t[nProjPads];
938 vectorSetShort(projPadToGrp, 0, nProjPads);
950 printf(
"[buildGroupOfPads] Group processing\n");
951 printf(
"----------------\n");
957 nbrOfProjGroups = getConnectedComponentsOfProjPadsWOSinglePads();
965 Groups_t grpToCathGrp[nbrOfProjGroups + 1];
966 if (nbrOfCathodePlanes == 1) {
968 int nCathPads = pads[singleCathPlaneID]->
getNbrOfPads();
969 cathGroup[singleCathPlaneID] =
new Groups_t[nCathPads];
970 vectorCopyShort(projPadToGrp, nCathPads, cathGroup[singleCathPlaneID]);
971 nCathGroups = nbrOfProjGroups;
972 nGroups = nCathGroups;
974 for (
int g = 0;
g < (nbrOfProjGroups + 1);
g++) {
979 cathGroup[singleCathPlaneID], grpToCathGrp, nGroups);
981 if (nNewGroups > 0) {
982 throw std::overflow_error(
"New group with one cathode plane ?????");
984 nGroups += nNewGroups;
994 cathGroup[0] =
new Groups_t[nCath0];
995 cathGroup[1] =
new Groups_t[nCath1];
996 vectorSetZeroShort(cathGroup[0], nCath0);
997 vectorSetZeroShort(cathGroup[1], nCath1);
999 printf(
"> Projected Groups nbrOfProjGroups=%d\n", nbrOfProjGroups);
1007 nGroups = assignPadsToGroupFromProj(nbrOfProjGroups);
1010 printf(
"> Groups after cathodes propagation nCathGroups=%d\n", nGroups);
1015 int nbrSinglePads = 0;
1016 for (
int c = 0;
c < 2;
c++) {
1018 if (cathGroup[
c][p] == 0) {
1023 int nbrMaxGroups = nGroups + nbrSinglePads;
1027 Mask_t mapGrpToGrp[nbrMaxGroups + 1];
1028 for (
int g = 0;
g < (nbrMaxGroups + 1);
g++) {
1037 nGroups += nNewGrpCath0;
1040 for (
int p = 0; p < nbrCath1; p++) {
1041 cathGroup[1][p] = mapGrpToGrp[cathGroup[1][p]];
1044 for (
int p = 0; p < nProjPads; p++) {
1045 projPadToGrp[p] = mapGrpToGrp[projPadToGrp[p]];
1048 printf(
"> addIsolatedPadInGroups in cath-0 nNewGroups =%d\n", nGroups);
1058 nGroups += nNewGrpCath1;
1060 for (
int p = 0; p < nbrCath0; p++) {
1061 cathGroup[0][p] = mapGrpToGrp[cathGroup[0][p]];
1064 for (
int p = 0; p < nProjPads; p++) {
1065 projPadToGrp[p] = mapGrpToGrp[projPadToGrp[p]];
1068 printf(
"> addIsolatedPadInGroups in cath-1 nNewGroups =%d\n", nGroups);
1072 removeLowChargedGroups(nGroups);
1076 int nNewGroups = renumberGroups(mapGrpToGrp, nGroups);
1078 printf(
"> Groups after renumbering nGroups=%d\n", nGroups);
1080 printf(
" nNewGrpCath0=%d, nNewGrpCath1=%d, nGroups=%d\n", nNewGrpCath0,
1081 nNewGrpCath1, nGroups);
1087 for (
int p = 0; p < nProjPads; p++) {
1088 projPadToGrp[p] = mapGrpToGrp[projPadToGrp[p]];
1091 nGroups = nNewGroups;
1093 updateProjectionGroups();
1097 printf(
" > Final Groups %d\n", nGroups);
1104int ClusterPEM::getConnectedComponentsOfProjPadsWOSinglePads()
1113 vectorSetZeroShort(projPadToGrp, N);
1115 int nbrOfPadSetInGrp = 0;
1117 short* curPadGrp = projPadToGrp;
1118 short currentGrpId = 0;
1125 "> Extract connected components "
1126 "[getConnectedComponentsOfProjPadsWOIsolatedPads]\n");
1128 while (nbrOfPadSetInGrp < N) {
1130 for (; (curPadGrp < &projPadToGrp[N]) && *curPadGrp != 0;) {
1133 k = curPadGrp - projPadToGrp;
1135 printf(
" k=%d, nbrOfPadSetInGrp g=%d: n=%d\n", k, currentGrpId,
1141 if (aloneKPads && (aloneKPads[k] != -1)) {
1144 printf(
" isolated pad %d\n", k);
1146 projPadToGrp[k] = -1;
1152 printf(
" New Grp, pad k=%d in new grp=%d\n", k, currentGrpId);
1154 projPadToGrp[k] = currentGrpId;
1157 neighToDo[startIdx] = k;
1160 for (; startIdx < endIdx; startIdx++) {
1161 i = neighToDo[startIdx];
1163 printf(
" propagate grp to neighbours of i=%d ",
i);
1167 for (
PadIdx_t* neigh_ptr = getTheFirtsNeighborOf(neigh,
i);
1168 *neigh_ptr != -1; neigh_ptr++) {
1171 if (projPadToGrp[
j] == 0) {
1175 if (aloneKPads && (aloneKPads[
j] != -1)) {
1177 printf(
" isolated pad %d, ",
j);
1179 projPadToGrp[
j] = -1;
1186 projPadToGrp[
j] = currentGrpId;
1189 neighToDo[endIdx] =
j;
1200 for (
int k = 0; k < N; k++) {
1201 if (projPadToGrp[k] == -1) {
1202 projPadToGrp[k] = 0;
1206 return currentGrpId;
1226int ClusterPEM::assignPadsToGroupFromProj(
int nGrp)
1229 short matGrpGrp[(nGrp + 1) * (nGrp + 1)];
1230 vectorSetZeroShort(matGrpGrp, (nGrp + 1) * (nGrp + 1));
1235 printf(
"[AssignPadsToGroupFromProj] Assign cath-grp from proj-grp \n");
1245 for (
int k = 0; k < nProjPads; k++) {
1246 g = projPadToGrp[k];
1257 prevGroup = cathGroup[0][
i];
1258 if ((prevGroup == 0) || (prevGroup ==
g)) {
1261 cathGroup[0][
i] =
g;
1262 matGrpGrp[
g * (nGrp + 1) +
g] = 1;
1268 cathGroup[0][
i] = std::min(
g, prevGroup);
1269 matGrpGrp[
g * (nGrp + 1) + prevGroup] = 1;
1270 matGrpGrp[prevGroup * (nGrp + 1) +
g] = 1;
1280 prevGroup = cathGroup[1][
j];
1282 if ((prevGroup == 0) || (prevGroup ==
g)) {
1284 cathGroup[1][
j] =
g;
1285 matGrpGrp[
g * (nGrp + 1) +
g] = 1;
1289 cathGroup[1][
j] = std::min(
g, prevGroup);
1290 matGrpGrp[
g * (nGrp + 1) + prevGroup] = 1;
1291 matGrpGrp[prevGroup * (nGrp + 1) +
g] = 1;
1304 vectorSetZeroShort(grpToMergedGrp, nGrp + 1);
1308 while (iGroup < (nGrp + 1)) {
1310 if (grpToMergedGrp[iGroup] == 0) {
1312 grpToMergedGrp[iGroup] = iGroup;
1314 curGroup = grpToMergedGrp[iGroup];
1317 int ishift = iGroup * (nGrp + 1);
1319 for (
int j = iGroup + 1;
j < (nGrp + 1);
j++) {
1320 if (matGrpGrp[ishift +
j]) {
1322 if (grpToMergedGrp[
j] == 0) {
1325 grpToMergedGrp[
j] = curGroup;
1332 grpToMergedGrp[curGroup] = grpToMergedGrp[
j];
1333 for (
int g = 1;
g < nGrp + 1;
g++) {
1334 if (grpToMergedGrp[
g] == curGroup) {
1335 grpToMergedGrp[
g] = grpToMergedGrp[
j];
1338 curGroup = grpToMergedGrp[
j];
1354 vectorSetZeroShort(map, (nGrp + 1));
1355 for (
int g = 1;
g < (nGrp + 1);
g++) {
1356 int gm = grpToMergedGrp[
g];
1359 map[gm] = newGroupID;
1363 for (
int g = 1;
g < (nGrp + 1);
g++) {
1364 grpToMergedGrp[
g] = map[grpToMergedGrp[
g]];
1372 for (
int c = 0;
c < 2;
c++) {
1375 cathGroup[
c][p] = grpToMergedGrp[std::abs(cathGroup[
c][p])];
1380 for (
int c = 0;
c < 2;
c++) {
1383 printf(
" [assignPadsToGroupFromProj] pad %d with no group\n", p);
1390 vectorMapShort(projPadToGrp, grpToMergedGrp, nProjPads);
1401 if (nbrOfPads == 1) {
1405 for (
int c = 0;
c < 2;
c++) {
1416int ClusterPEM::assignGroupToCathPads()
1422 int nGrp = nbrOfProjGroups;
1430 Groups_t* cath0ToGrpFromProj = cathGroup[0];
1431 Groups_t* cath1ToGrpFromProj = cathGroup[1];
1432 vectorSetZeroShort(cathGroup[0], nCath0);
1433 vectorSetZeroShort(cathGroup[1], nCath1);
1435 Groups_t projGrpToCathGrp[nGrp + 1];
1436 vectorSetZeroShort(projGrpToCathGrp, nGrp + 1);
1440 printf(
" [assignGroupToCathPads]\n");
1444 short g, prevGroup0, prevGroup1;
1445 if (nbrOfCathodePlanes == 1) {
1447 vectorCopyShort(projPadToGrp, pads[singleCathPlaneID]->
getNbrOfPads(),
1448 cathGroup[singleCathPlaneID]);
1452 for (
int k = 0; k < nProjPads; k++) {
1454 g = projPadToGrp[k];
1459 printf(
"map k=%d g=%d to i=%d/%d, j=%d/%d\n", k,
g,
i, nCath0,
j, nCath1);
1464 if ((
i >= 0) && (nCath0 != 0)) {
1466 prevGroup0 = cath0ToGrpFromProj[
i];
1467 if (prevGroup0 == 0) {
1468 if ((projGrpToCathGrp[
g] == 0) && (
g != 0)) {
1470 projGrpToCathGrp[
g] = nCathGrp;
1472 cath0ToGrpFromProj[
i] = projGrpToCathGrp[
g];
1474 }
else if (prevGroup0 != projGrpToCathGrp[
g]) {
1478 printf(
">>> Fuse group g=%d prevGrp0=%d, projGrpToCathGrp[g]=%d\n",
g,
1479 prevGroup0, projGrpToCathGrp[
g]);
1482 Groups_t minGroup = (projGrpToCathGrp[
g] != 0)
1483 ? std::min(projGrpToCathGrp[
g], prevGroup0)
1485 projGrpToCathGrp[
g] = minGroup;
1492 if ((
j >= 0) && (nCath1 != 0)) {
1493 prevGroup1 = cath1ToGrpFromProj[
j];
1494 if (prevGroup1 == 0) {
1495 if ((projGrpToCathGrp[
g] == 0) && (
g != 0)) {
1497 projGrpToCathGrp[
g] = nCathGrp;
1499 cath1ToGrpFromProj[
j] = projGrpToCathGrp[
g];
1500 }
else if (prevGroup1 != projGrpToCathGrp[
g]) {
1501 printf(
">>> Fuse group g=%d prevGrp1=%d, projGrpToCathGrp[g]=%d\n",
g,
1502 prevGroup1, projGrpToCathGrp[
g]);
1505 Groups_t minGroup = (projGrpToCathGrp[
g] != 0)
1506 ? std::min(projGrpToCathGrp[
g], prevGroup1)
1508 projGrpToCathGrp[
g] = minGroup;
1515 printf(
" [assignGroupToCathPads] before renumbering nCathGrp=%d\n", nCathGrp);
1523 int nNewGrp = renumberGroupsFromMap(projGrpToCathGrp, nGrp);
1525 if (nNewGrp != nGrp) {
1527 vectorMapShort(cath0ToGrpFromProj, projGrpToCathGrp, nCath0);
1528 vectorMapShort(cath1ToGrpFromProj, projGrpToCathGrp, nCath1);
1538 for (
i = 0;
i < nProjPads;
i++) {
1539 projPadToGrp[
i] = projGrpToCathGrp[projPadToGrp[
i]];
1554 for (
int c = 0;
c < 2;
c++) {
1556 for (
int p = 0; p < nbrPads; p++) {
1557 if (cathGroup[
c][p] ==
g) {
1567 int cStart(0), cEnd(0);
1571 }
else if (plane == 0) {
1578 double xBary(0), yBary(0), wCharges(0);
1579 for (
int c = cStart;
c < cEnd;
c++) {
1585 for (
int p = 0; p < P; p++) {
1586 xBary += charges[p] * X[p];
1587 yBary += charges[p] * Y[p];
1588 wCharges += charges[p];
1592 xBary = xBary / wCharges;
1593 yBary = yBary / wCharges;
1595 return std::make_pair(xBary, yBary);
1601 const double*
x = pads[
c]->
getX();
1602 const double*
y = pads[
c]->
getY();
1603 const double* dx = pads[
c]->
getDX();
1604 const double* dy = pads[
c]->
getDY();
1605 double xMin = vectorMin(
x, N);
1606 double xMax = vectorMax(
x, N);
1607 double yMin = vectorMin(
y, N);
1608 double yMax = vectorMax(
y, N);
1609 double dxMin = 2 * vectorMin(dx, N);
1610 double dyMin = 2 * vectorMin(dy, N);
1612 int nXMax = (
int)((xMax - xMin) / dxMin + 0.5) + 1;
1613 int nYMax = (
int)((
yMax - yMin) / dyMin + 0.5) + 1;
1616 vectorSetShort(xSampling, 0, nXMax);
1617 vectorSetShort(ySampling, 0, nYMax);
1619 for (
int i = 0;
i < N;
i++) {
1622 int xIdx = (
int)((
x[
i] - xMin) / dxMin + 0.5);
1623 int yIdx = (
int)((
y[
i] - yMin) / dyMin + 0.5);
1624 if (xSampling[xIdx] == 0) {
1626 xSampling[xIdx] = 1;
1629 if (ySampling[yIdx] == 0) {
1631 ySampling[yIdx] = 1;
1635 return std::make_pair(nX, nY);
1638void ClusterPEM::removeLowChargedGroups(
int nGroups)
1640 int nbrPadsInGroup[2][nGroups + 1];
1641 double chargeInGroup[2][nGroups + 1];
1642 vectorSetInt(nbrPadsInGroup[0], 0, nGroups);
1643 vectorSetInt(nbrPadsInGroup[1], 0, nGroups);
1644 vectorSet(chargeInGroup[0], 0, nGroups);
1645 vectorSet(chargeInGroup[1], 0, nGroups);
1649 for (
int c = 0;
c < 2;
c++) {
1652 nbrCath += (nbrPads != 0) ? 1 : 0;
1653 for (
int p = 0; p < nbrPads; p++) {
1654 nbrPadsInGroup[
c][cathGroup[
c][p]]++;
1655 chargeInGroup[
c][cathGroup[
c][p]] += q[p];
1662 double chargePerCath = chargeInGroup[0][
g] + chargeInGroup[1][
g];
1663 chargePerCath = chargePerCath / 2;
1664 double maxCharge = std::fmax(chargeInGroup[0][
g], chargeInGroup[1][
g]);
1665 int nbrPads = nbrPadsInGroup[0][
g] + nbrPadsInGroup[1][
g];
1672 for (
int c = 0;
c < 2;
c++) {
1674 for (
int p = 0; p < nbrPads; p++) {
1675 if (cathGroup[
c][p] ==
g) {
1676 cathGroup[
c][p] = 0;
1681 int nbrPads = chargeInGroup[0][
g] + chargeInGroup[1][
g];
1682 printf(
"> [removeLowChargedGroups] Remove low charge group g=%d, charge per cath= %f, #pads=%d \n",
g, maxCharge, nbrPads);
1692int ClusterPEM::filterFitModelOnSmallChargedSeeds(Pads& pads,
double* theta,
int K,
1693 Mask_t* maskFilteredTheta)
1698 double* w_ =
getW(theta, K);
1701 int kSelectedInit = vectorSumShort(maskFilteredTheta, K);
1702 double meanCharge = pads.getMeanTotalCharge();
1709 for (
int k = 0; k < K; k++) {
1710 wSum += (maskFilteredTheta[k] * w_[k]);
1713 double norm = meanCharge / wSum;
1714 for (
int k = 0; k < K; k++) {
1715 w[k] = maskFilteredTheta[k] * w_[k] * norm;
1717 printf(
"[filterFitModelOnSmallCharge] remove the %dth seeds, low charge=%f \n", k,
w[k]);
1719 maskFilteredTheta[k] = maskFilteredTheta[k] && (
w[k] > cutOff);
1720 kWFilter += (maskFilteredTheta[k] && (
w[k] > cutOff));
1723 printf(
"[filterFitModelOnSmallCharge] remove %d seeds (cutOff=%5.2f)\n",
1724 kSelectedInit - kWFilter, cutOff);
1730int ClusterPEM::filterFitModelOnClusterRegion(Pads& pads,
double* theta,
int K,
1731 Mask_t* maskFilteredTheta)
1736 const double*
x = pads.getX();
1737 const double*
y = pads.getY();
1738 const double* dx = pads.getDX();
1739 const double* dy = pads.getDY();
1740 int N = pads.getNbrOfPads();
1743 int kSpacialFilter = 0;
1744 vectorAddVector(
x, -1.0, dx, N, xyTmp);
1745 double xMin = vectorMin(xyTmp, N);
1746 vectorAddVector(
x, +1.0, dx, N, xyTmp);
1747 double xMax = vectorMax(xyTmp, N);
1748 vectorAddVector(
y, -1.0, dy, N, xyTmp);
1749 double yMin = vectorMin(xyTmp, N);
1750 vectorAddVector(
y, +1.0, dy, N, xyTmp);
1751 double yMax = vectorMax(xyTmp, N);
1752 double* muX =
getMuX(theta, K);
1753 double* muY =
getMuY(theta, K);
1754 for (
int k = 0; k < K; k++) {
1755 maskFilteredTheta[k] = 0;
1756 if ((muX[k] > xMin) && (muX[k] < xMax)) {
1757 if ((muY[k] > yMin) && (muY[k] <
yMax)) {
1758 maskFilteredTheta[k] = 1;
1765 printf(
"[filterFitModelOnClusterRegion] ---> Out of the frame; removing %d hit\n", K - kSpacialFilter);
1770 double cutOff = 0.02 / kSpacialFilter;
1772 double* w_ =
getW(theta, K);
1776 for (
int k = 0; k < K; k++) {
1777 wSum += (maskFilteredTheta[k] * w_[k]);
1780 double norm = 1.0 / wSum;
1781 for (
int k = 0; k < K; k++) {
1782 w[k] = maskFilteredTheta[k] * w_[k] * norm;
1783 maskFilteredTheta[k] = maskFilteredTheta[k] && (
w[k] > cutOff);
1784 kWFilter += (maskFilteredTheta[k] && (
w[k] > cutOff));
1788 "[filterFitModelOnClusterRegion] At least one hit such as w[k] < "
1789 "(0.05 / K) = %8.4f) -> removing %d hit\n",
1790 cutOff, kSpacialFilter - kWFilter);
1797int ClusterPEM::filterFitModelOnSpaceVariations(
const double* thetaEM,
int kEM,
1798 double* thetaFit,
int kFit,
1799 Mask_t* maskFilteredTheta)
1803 int kSpacialFilter = 0;
1811 double* muX =
getMuX(thetaFit, kFit);
1812 double* muY =
getMuY(thetaFit, kFit);
1813 double xTmp[kEM], yTmp[kEM];
1817 for (
int k = 0; k < kFit; k++) {
1820 vectorAddScalar(muEMX, -muX[k], kEM, xTmp);
1821 vectorMultVector(xTmp, xTmp, kEM, xTmp);
1822 vectorAddScalar(muEMY, -muY[k], kEM, yTmp);
1823 vectorMultVector(yTmp, yTmp, kEM, yTmp);
1824 vectorAddVector(xTmp, 1.0, yTmp, kEM, xTmp);
1826 int kMin = vectorArgMin(xTmp, kEM);
1831 double xMin = muEMX[kMin] - 3 * muEMDx[kMin];
1832 double xMax = muEMX[kMin] + 3 * muEMDx[kMin];
1833 double yMin = muEMY[kMin] - 3 * muEMDy[kMin];
1834 double yMax = muEMY[kMin] + 3 * muEMDy[kMin];
1836 if (((muX[k] > xMin) && (muX[k] < xMax)) &&
1837 ((muY[k] > yMin) && (muY[k] <
yMax))) {
1842 printf(
"[filterFitModelOnSpaceVariations] ---> too much drift; deltaX/Y=(%6.2f,%6.2f) ---> k=%3d removed\n",
1843 muEMX[k] - muX[k], muEMY[k] - muY[k], k);
1844 printf(
"[filterFitModelOnSpaceVariations] ---> too much drift; EM=(%6.2f,%6.2f) dxyEM=(%6.2f,%6.2f) Fit=(%6.2f,%6.2f)\n",
1845 muEMX[k], muEMY[k], muEMDx[k], muEMDy[k], muX[k], muY[k]);
1849 maskFilteredTheta[k] = 0;
1853 printf(
"[filterFitModelOnSpaceVariations] ---> Final filter: %d hit(s) removed\n", kFit - kSpacialFilter);
1859 double*
w =
getW(thetaFit, kFit);
1860 for (
int k = 0; k < kFit; k++) {
1861 if (maskFilteredTheta[k]) {
1862 for (
int l = k + 1; l < kFit; l++) {
1863 if (maskFilteredTheta[l]) {
1865 double maxErrorX = 2.0 * std::fmin(muEMDx[k], muEMDx[l]);
1866 double maxErrorY = 2.0 * std::fmin(muEMDy[k], muEMDy[l]);
1867 bool xClose = std::fabs(muX[k] - muX[l]) < maxErrorX;
1868 bool yClose = std::fabs(muY[k] - muY[l]) < maxErrorY;
1871 if (xClose && yClose) {
1874 maskFilteredTheta[l] = 0;
1877 maskFilteredTheta[k] = 0;
1885 int kCloseFilter = vectorSumShort(maskFilteredTheta, kFit);
1888 "[filterFitModelOnSpaceVariations] ---> Close seeds: removed %d close seeds\n",
1889 kSpacialFilter - kCloseFilter);
1891 return kCloseFilter;
1898 int nFit = nbrCath0 + nbrCath1;
1905 double* thetaFit =
new double[kInit * 5];
1906 vectorSet(thetaFit, 0, kInit * 5);
1908 if (nbrOfCathodePlanes == 1) {
1909 std::pair<int, int> nXY =
getNxNy(singleCathPlaneID);
1925 int dimOfParameters = 3;
1929 Pads* fitPads =
nullptr;
1931 if ((kInit == 1) && (nbrOfCathodePlanes == 1)) {
1934 double* muX =
getMuX(thetaInit, kInit);
1935 double* muY =
getMuY(thetaInit, kInit);
1937 muX[0] = bary.first;
1938 muY[0] = bary.second;
1941 printf(
"fit nbrCath=%d nbrPads=(%d, %d) nbrObsPads=(%d, %d) nX/Y=(%d, %d)\n",
1946 if ((nbrOfCathodePlanes == 1) && ((nX == 1) || (nY == 1))) {
1947 dimOfParameters = 2;
1949 axe = (nX == 1) ? 1 : 0;
1950 fitPads = pads[singleCathPlaneID];
1951 pads[singleCathPlaneID]->
setCathodes(singleCathPlaneID);
1999 double pError[dimOfParameters * kInit * dimOfParameters * kInit];
2001 printf(
"Starting the fitting\n");
2002 printf(
"- # cath0, cath1 for fitting: %2d %2d\n",
getNbrOfPads(0),
2004 printTheta(
"- thetaInit", 1.0, thetaInit, kInit);
2007 if ((kInit * dimOfParameters - 1) <= nFit) {
2015 fitMathieson(*fitPads, thetaInit, kInit, dimOfParameters, axe, processFitVerbose, thetaFit,
2018 printf(
"---> Fitting parameters to large : k=%d, (3 or 2)*k-1=%d, nFit=%d\n",
2019 kInit, kInit * dimOfParameters - 1, nFit);
2020 printf(
" keep the EM solution\n");
2021 vectorCopy(thetaInit, kInit * 5, thetaFit);
2024 printTheta(
"- thetaFit", 1.0, thetaFit, kInit);
2027 Mask_t maskFilterFit[kInit];
2029 vectorSetShort(maskFilterFit, 1, kInit);
2038 filteredK = filterFitModelOnSmallChargedSeeds(*fitPads, thetaFit, kInit,
2040 double filteredTheta[5 * filteredK];
2041 if ((filteredK != kInit) && (nFit >= filteredK)) {
2043 printf(
"Filtering the fitting K=%d >= K=%d\n", nFit, filteredK);
2046 if (filteredK > 0) {
2055 copyTheta(filteredTheta, filteredK, thetaFit, filteredK, filteredK);
2071 printf(
"[Cluster.fit] nbrOfPadsLimit reach. Keep the EM Result: nFit=%d >= nbrOfPadsLimitForTheFitting=%d\n",
2074 vectorCopy(thetaInit, kInit * 5, thetaFit);
2080 return std::make_pair(finalK, thetaFit);
2085int ClusterPEM::renumberGroupsFromMap(
short* grpToGrp,
int nGrp)
2089 int maxIdx = vectorMaxShort(grpToGrp, nGrp + 1);
2090 std::vector<short>
counters(maxIdx + 1);
2091 vectorSetShort(
counters.data(), 0, maxIdx + 1);
2093 for (
int g = 1;
g <= nGrp;
g++) {
2094 if (grpToGrp[
g] != 0) {
2099 for (
int g = 1;
g <= maxIdx;
g++) {
2106 for (
int g = 1;
g <= nGrp;
g++) {
2112int ClusterPEM::renumberGroups(
Mask_t* grpToGrp,
int nGrp)
2115 for (
int g = 0;
g < (nGrp + 1);
g++) {
2118 for (
int c = 0;
c < 2;
c++) {
2119 Mask_t* cathToGrp = cathGroup[
c];
2120 int nbrCath = pads[
c]->getNbrOfPads();
2121 for (
int p = 0; p < nbrCath; p++) {
2122 int g = cathToGrp[p];
2126 if (grpToGrp[
g] == 0) {
2130 grpToGrp[
g] = currentGrp;
2131 cathToGrp[p] = currentGrp;
2134 cathToGrp[p] = grpToGrp[
g];
2139 int newNbrGroups = currentGrp;
2141 printf(
"> Groups renumbering [renumberGroups] newNbrGroups=%d\n",
2146 return newNbrGroups;
2149Pads* ClusterPEM::findLocalMaxWithRefinement(
double* thetaL,
int nbrOfPadsInTheGroupCath)
2154 Pads* cath0 = pads[0];
2155 Pads* cath1 = pads[1];
2156 Pads* projPads = projectedPads;
2160 double preClusterCharge = cWeight0 + cWeight1;
2161 cWeight0 /= preClusterCharge;
2162 cWeight1 /= preClusterCharge;
2164 double dxMinPadSize = 1000.0;
2165 double dyMinPadSize = 1000.0;
2166 double minDY[2] = {1000.0, 1000.0};
2170 dxMinPadSize = vectorMin(cath0->getDX(), n0);
2173 dyMinPadSize = vectorMin(cath1->getDY(), n1);
2176 int chId = chamberId;
2178 printf(
" - [findLocalMaxWithRefinement]\n");
2182 int maxNbrOfPixels = 4 * projPads->getNbrOfPads();
2184 Pads*
pixels =
new Pads(projPads, maxNbrOfPixels);
2189 int nPads = mergedPads->getNbrOfPads();
2191 Pads* localMax =
nullptr;
2192 Pads* saveLocalMax =
nullptr;
2193 std::pair<double, double> chi2;
2194 int dof, nParameters;
2201 double* Cij =
new double[nPads * maxNbrOfPixels];
2217 int nbrLocalMax = 0;
2218 int nbrPrevLocalMax = 0;
2219 double previousCriterion = DBL_MAX;
2220 double criterion = DBL_MAX;
2225 " Macro nParam ndof ndof chi2 chi2/ndof chi2/ndof chi2/ndof chi2/ndof ch2/ndof\n"
2226 " It. - cath0 cath1 - - cath-0 cath-1 sum 0/1 weight-sum\n");
2231 if (localMax !=
nullptr) {
2232 if (saveLocalMax !=
nullptr) {
2233 delete saveLocalMax;
2237 previousCriterion = criterion;
2241 nIterations[macroIt]);
2246 std::vector<PadIdx_t> newPixelIdx;
2247 if (localMax !=
nullptr) {
2250 localMax =
pixels->extractLocalMax(newPixelIdx, dxMinPadSize, dyMinPadSize);
2251 nbrLocalMax = newPixelIdx.size();
2254 for (
int t = 0; t < newPixelIdx.size(); t++) {
2255 int idx = newPixelIdx[t];
2256 printf(
" localMax idx=%d, xy(%f, %f), q[idx]=%f, localMax.q[t]=%f max(pixels)=%f \n",
2257 idx,
pixels->getX()[idx],
pixels->getY()[idx],
pixels->getCharges()[idx], localMax->getCharges()[t], vectorMax(
pixels->getCharges(),
pixels->getNbrOfPads()));
2260 nParameters = localMax->getNbrOfPads();
2261 dof = nMaxPads - 3 * nParameters + 1;
2265 double chi20 = chi2.first;
2266 double chi21 = chi2.second;
2276 if ((ndof0 <= 0) && (ndof1 <= 0)) {
2298 criterion = cWeight0 * sqrt(chi20 / ndof0) + cWeight1 * sqrt(chi21 / ndof1);
2306 " %2d %3d %3d %3d %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",
2307 macroIt, nParameters, ndof0, ndof1, chi20 + chi21, sqrt((chi20 + chi21) / dof),
2308 sqrt(chi20 / ndof0), sqrt(chi21 / ndof1),
2309 sqrt(chi20 / ndof0) + sqrt(chi21 / ndof1),
2317 pixels->refineLocalMaxAndUpdateCij(*mergedPads, newPixelIdx, Cij);
2325 ((criterion < 1.0 * previousCriterion) || (macroIt < 3)) && (macroIt < nMacroIterations);
2328 nbrPrevLocalMax = nbrLocalMax;
2331 if (criterion < 1.0 * previousCriterion) {
2332 delete saveLocalMax;
2335 localMax = saveLocalMax;
2345Pads* ClusterPEM::findLocalMaxWithoutRefinement(
double* thetaL,
int nbrOfPadsInTheGroupCath)
2350 Pads* cath0 = pads[0];
2351 Pads* cath1 = pads[1];
2352 Pads* projPads = projectedPads;
2356 double preClusterCharge = cWeight0 + cWeight1;
2357 cWeight0 /= preClusterCharge;
2358 cWeight1 /= preClusterCharge;
2359 double dxMinPadSize, dyMinPadSize;
2363 dxMinPadSize = 0.5 * vectorMin(cath0->getDX(), n0);
2366 dyMinPadSize = 0.5 * vectorMin(cath1->getDY(), n1);
2369 dxMinPadSize = 1.0e-4;
2370 dyMinPadSize = 1.0e-4;
2372 int chId = chamberId;
2374 printf(
" - [findLocalMaxWithoutRefinement]\n");
2384 int maxNbrOfPixels = projPads->getNbrOfPads();
2385 if (maxNbrOfPixels == 0) {
2386 throw std::out_of_range(
"[findLocalMaxWithoutRefinement] No projected pads");
2389 Pads*
pixels =
new Pads(projPads, maxNbrOfPixels);
2394 int nPads = mergedPads->getNbrOfPads();
2397 Pads* localMax =
nullptr;
2398 Pads* saveLocalMax =
nullptr;
2399 std::pair<double, double> chi2;
2400 int dof, nParameters;
2407 double* Cij =
new double[nPads * maxNbrOfPixels];
2423 int nbrLocalMax = 0;
2424 int nbrPrevLocalMax = 0;
2425 double previousCriterion = DBL_MAX;
2426 double criterion = DBL_MAX;
2431 " Macro nParam ndof ndof chi2 chi2/ndof chi2/ndof chi2/ndof chi2/ndof ch2/ndof\n"
2432 " It. - cath0 cath1 - - cath-0 cath-1 sum 0/1 weight-sum\n");
2435 int nTotalIterations = nPads / 10;
2436 int chunk = ceil(
float(nTotalIterations) / (nMacroIterations + 1));
2437 chunk = std::min(chunk, 5);
2438 for (
int it = 0; it < nMacroIterations; it++) {
2439 nIterations[it] = (it + 1) * chunk;
2441 nIterations[nMacroIterations - 1] += chunk;
2443 printf(
" Macro Iterations: nIterations[0, 1, ..,nMacroIterations-1] = [%d, %d, ..., %d] \n",
2444 nIterations[0], nIterations[1], nIterations[nMacroIterations - 1]);
2450 if (localMax !=
nullptr) {
2451 if (saveLocalMax !=
nullptr) {
2452 delete saveLocalMax;
2456 previousCriterion = criterion;
2467 std::vector<PadIdx_t> newPixelIdx;
2468 if (localMax !=
nullptr) {
2471 localMax =
pixels->extractLocalMaxOnCoarsePads_Remanent(newPixelIdx, dxMinPadSize, dyMinPadSize);
2474 nbrLocalMax = newPixelIdx.size();
2477 for (
int t = 0; t < newPixelIdx.size(); t++) {
2478 int idx = newPixelIdx[t];
2479 printf(
" localMax idx=%d, xy(%f, %f), q[idx]=%f, localMax.q[t]=%f max(pixels)=%f \n",
2480 idx,
pixels->getX()[idx],
pixels->getY()[idx],
pixels->getCharges()[idx], localMax->getCharges()[t], vectorMax(
pixels->getCharges(),
pixels->getNbrOfPads()));
2483 nParameters = localMax->getNbrOfPads();
2484 dof = nMaxPads - 3 * nParameters + 1;
2488 double chi20 = chi2.first;
2489 double chi21 = chi2.second;
2499 if ((ndof0 <= 0) && (ndof1 <= 0)) {
2521 criterion = cWeight0 * sqrt(chi20 / ndof0) + cWeight1 * sqrt(chi21 / ndof1);
2529 " %2d %3d %3d %3d %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",
2530 macroIt, nParameters, ndof0, ndof1, chi20 + chi21, sqrt((chi20 + chi21) / dof),
2531 sqrt(chi20 / ndof0), sqrt(chi21 / ndof1),
2532 sqrt(chi20 / ndof0) + sqrt(chi21 / ndof1),
2541 ((criterion < 1.0 * previousCriterion) && (macroIt < nMacroIterations));
2545 nbrPrevLocalMax = nbrLocalMax;
2551 if (criterion < 1.0 * previousCriterion) {
2552 delete saveLocalMax;
2555 localMax = saveLocalMax;
2569 Pads* cath0 = pads[0];
2570 Pads* cath1 = pads[1];
2571 Pads* projPads = projectedPads;
2576 double clusterCharge = cWeight0 + cWeight1;
2577 cWeight0 /= clusterCharge;
2578 cWeight1 /= clusterCharge;
2580 int chId = chamberId;
2582 printf(
" - [findLocalMaxWithPEM]\n");
2590 printf(
" Trivial case: only one pad\n");
2593 double*
w =
getW(thetaL, nbrOfPadsInTheGroupCath);
2594 double* muX =
getMuX(thetaL, nbrOfPadsInTheGroupCath);
2595 double* muY =
getMuY(thetaL, nbrOfPadsInTheGroupCath);
2596 double* muDX =
getVarX(thetaL, nbrOfPadsInTheGroupCath);
2597 double* muDY =
getVarY(thetaL, nbrOfPadsInTheGroupCath);
2599 muX[0] = projPads->
getX()[0];
2600 muY[0] = projPads->
getY()[0];
2601 muDX[0] = projPads->
getDX()[0] * 0.5;
2602 muDY[0] = projPads->
getDY()[0] * 0.5;
2606 Pads* localMax =
nullptr;
2611 double minDX[2] = {1000.0, 1000.0};
2612 double minDY[2] = {1000.0, 1000.0};
2616 minDX[0] = vectorMin(cath0->
getDX(), n0);
2617 minDY[0] = vectorMin(cath0->
getDY(), n0);
2620 minDX[1] = vectorMin(cath1->
getDX(), n1);
2621 minDY[1] = vectorMin(cath1->
getDY(), n1);
2625 bool largePads = (minDX[0] > 3.5) || (minDY[1] > 3.5);
2628 localMax = findLocalMaxWithoutRefinement(thetaL, nbrOfPadsInTheGroupCath);
2631 localMax = findLocalMaxWithRefinement(thetaL, nbrOfPadsInTheGroupCath);
2648 double cutRatio = 0.01;
2665 printf(
"seed selection: nbr Max parameters =%d, nLocMax=%d\n",
2668 "seed selection: Reduce the nbr of solutions to fit: Take %d/%d "
2676 const double* qLocalMax = localMax->
getCharges();
2678 [=](
int a,
int b) { return (qLocalMax[a] > qLocalMax[b]); });
2680 qCut = qLocalMax[
index[nMaxSolutions - 1]] - 1.e-03;
2687 double cutRatio = 0.7;
2688 cutRatio = largePads ? 0.0 : cutRatio;
2698 int removedLocMax = k0 - k;
2702 " > seed selection: Final cut -> %d percent (qcut=%8.2f), number of "
2703 "local max removed = %d\n",
2704 int(cutRatio * 100), qCut, removedLocMax);
2709 int K = std::min(K0, nbrOfPadsInTheGroupCath);
2710 double*
w =
getW(thetaL, nbrOfPadsInTheGroupCath);
2711 double* muX =
getMuX(thetaL, nbrOfPadsInTheGroupCath);
2712 double* muY =
getMuY(thetaL, nbrOfPadsInTheGroupCath);
2713 double* varX =
getVarX(thetaL, nbrOfPadsInTheGroupCath);
2714 double* varY =
getVarY(thetaL, nbrOfPadsInTheGroupCath);
2716 const double* xl = localMax->
getX();
2717 const double* yl = localMax->
getY();
2718 const double* dxl = localMax->
getDX();
2719 const double* dyl = localMax->
getDY();
2720 for (
int k = 0; k < K; k++) {
2727 printf(
" k=%d w=%f, XY=%f,%f varXY=%f,%f\n", k,
w[k], muX[k], muY[k], varX[k], varY[k]);
2741 Pads* cath0 = pads[0];
2742 Pads* cath1 = pads[1];
2743 Pads* projPads = projectedPads;
2747 double preClusterCharge = cWeight0 + cWeight1;
2748 cWeight0 /= preClusterCharge;
2749 cWeight1 /= preClusterCharge;
2751 int chId = chamberId;
2753 printf(
" - [findLocalMaxWithPEM]\n");
2758 double*
w =
getW(thetaL, nbrOfPadsInTheGroupCath);
2759 double* muX =
getMuX(thetaL, nbrOfPadsInTheGroupCath);
2760 double* muY =
getMuY(thetaL, nbrOfPadsInTheGroupCath);
2761 double* muDX =
getVarX(thetaL, nbrOfPadsInTheGroupCath);
2762 double* muDY =
getVarY(thetaL, nbrOfPadsInTheGroupCath);
2764 muX[0] = projPads->
getX()[0];
2765 muY[0] = projPads->
getY()[0];
2766 muDX[0] = projPads->
getDX()[0] * 0.5;
2767 muDY[0] = projPads->
getDY()[0] * 0.5;
2781 int nPixels =
pixels->getNbrOfPads();
2786 Pads* localMax =
nullptr;
2787 Pads* saveLocalMax =
nullptr;
2788 std::pair<double, double> chi2;
2789 int dof, nParameters;
2798 double* Cij =
new double[nPads * nPixels];
2843 double previousCriteriom = DBL_MAX;
2844 double criteriom = DBL_MAX;
2849 " Macro nParam chi2 chi2/ndof chi2/ndof chi2/ndof chi2/ndof ch2/ndof\n"
2850 " It. - - - cath-0 cath-1 sum 0/1 weight-sum\n");
2853 if (localMax !=
nullptr) {
2854 if (saveLocalMax !=
nullptr) {
2855 delete saveLocalMax;
2859 previousCriteriom = criteriom;
2875 nIterations[macroIt]);
2878 std::vector<PadIdx_t> newPixelIdx;
2889 dof = nMaxPads - 3 * nParameters + 1;
2890 double chi20 = chi2.first;
2891 double chi21 = chi2.second;
2907 criteriom = cWeight0 * sqrt(chi20 / ndof0) + cWeight1 * sqrt(chi21 / ndof1);
2913 " %2d %3d %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",
2914 macroIt, nParameters, chi20 + chi21, sqrt((chi20 + chi21) / dof),
2915 sqrt(chi20 / ndof0), sqrt(chi21 / ndof1),
2916 sqrt(chi20 / ndof0) + sqrt(chi21 / ndof1),
2917 cWeight0 * sqrt(chi20 / ndof0) + cWeight1 * sqrt(chi21 / ndof1));
2940 printf(
" min/max, %g, %g \n", vectorMin(
pixels->getCharges(), nPixels), vectorMax(
pixels->getCharges(), nPixels));
2942 (criteriom < 1.0 * previousCriteriom) && (macroIt < nMacroIterations);
2946 if (criteriom < 1.01 * previousCriteriom) {
2947 delete saveLocalMax;
2950 localMax = saveLocalMax;
2957 double cutRatio = 0.01;
2975 printf(
"seed selection: nbr Max parameters =%d, nLocMax=%d\n",
2978 "seed selection: Reduce the nbr of solutions to fit: Take %d/%d "
2986 const double* qLocalMax = localMax->
getCharges();
2988 [=](
int a,
int b) { return (qLocalMax[a] > qLocalMax[b]); });
2990 qCut = qLocalMax[
index[nMaxSolutions - 1]] - 1.e-03;
2998 " > seed selection: Final cut -> %d percent (qcut=%8.2f), number of "
2999 "local max removed = %d\n",
3000 int(cutRatio * 100), qCut, removedLocMax);
3005 int K = std::min(K0, nbrOfPadsInTheGroupCath);
3006 double*
w =
getW(thetaL, nbrOfPadsInTheGroupCath);
3007 double* muX =
getMuX(thetaL, nbrOfPadsInTheGroupCath);
3008 double* muY =
getMuY(thetaL, nbrOfPadsInTheGroupCath);
3009 double* varX =
getVarX(thetaL, nbrOfPadsInTheGroupCath);
3010 double* varY =
getVarY(thetaL, nbrOfPadsInTheGroupCath);
3012 const double* xl = localMax->
getX();
3013 const double* yl = localMax->
getY();
3014 const double* dxl = localMax->
getDX();
3015 const double* dyl = localMax->
getDY();
3016 for (
int k = 0; k < K; k++) {
3022 printf(
"k=%d XY=%f,%f varXY=%f,%f\n", k, muX[k], muY[k], varX[k], varY[k]);
3028 double rcond = 1.e-2;
3029 gsl_matrix_view Cij_gsl = gsl_matrix_view_array(Cij, nPixels, nPads);
3030 double* qPixelsStar =
new double[nPixels];
3031 gsl_vector_view qPixelsStar_gsl = gsl_vector_view_array(qPixelsStar, nPixels);
3046 gsl_matrix* CCii = gsl_matrix_alloc(nPixels, nPixels);
3047 gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1., &Cij_gsl.matrix, &Cij_gsl.matrix, 0., CCii);
3049 double* pix =
new double[nPixels];
3050 vectorSet(pix, 0.0, nPixels);
3052 gsl_vector_view pix_gsl = gsl_vector_view_array(pix, nPixels);
3053 gsl_blas_dgemv(CblasNoTrans, 1.0, pInv, &pix_gsl.vector, 0.0, &qPixelsStar_gsl.vector);
3054 vectorAddScalar(pix, -1, nPixels, pix);
3139 Pads* cath0 = pads[0];
3140 Pads* cath1 = pads[1];
3141 Pads* projPads = projectedPads;
3145 double preClusterCharge = cWeight0 + cWeight1;
3146 cWeight0 /= preClusterCharge;
3147 cWeight1 /= preClusterCharge;
3149 int chId = chamberId;
3151 printf(
" - [findLocalMaxWithPEM]\n");
3156 double*
w =
getW(thetaL, nbrOfPadsInTheGroupCath);
3157 double* muX =
getMuX(thetaL, nbrOfPadsInTheGroupCath);
3158 double* muY =
getMuY(thetaL, nbrOfPadsInTheGroupCath);
3159 double* muDX =
getVarX(thetaL, nbrOfPadsInTheGroupCath);
3160 double* muDY =
getVarY(thetaL, nbrOfPadsInTheGroupCath);
3162 muX[0] = projPads->
getX()[0];
3163 muY[0] = projPads->
getY()[0];
3164 muDX[0] = projPads->
getDX()[0] * 0.5;
3165 muDY[0] = projPads->
getDY()[0] * 0.5;
3179 int nPixels =
pixels->getNbrOfPads();
3184 Pads* localMax =
nullptr;
3185 Pads* saveLocalMax =
nullptr;
3186 std::pair<double, double> chi2;
3187 int dof, nParameters;
3196 double* Cij =
new double[nPads * nPixels];
3207 double previousCriteriom = DBL_MAX;
3208 double criteriom = DBL_MAX;
3213 " Macro nParam chi2 chi2/ndof chi2/ndof chi2/ndof chi2/ndof ch2/ndof\n"
3214 " It. - - - cath-0 cath-1 sum 0/1 weight-sum\n");
3217 if (localMax !=
nullptr) {
3218 if (saveLocalMax !=
nullptr) {
3219 delete saveLocalMax;
3223 previousCriteriom = criteriom;
3239 nIterations[macroIt]);
3242 std::vector<PadIdx_t> newPixelIdx;
3244 for (
int t = 0; t < newPixelIdx.size(); t++) {
3245 int idx = newPixelIdx[t];
3246 printf(
"localMax idx=%d, xy(%f, %f), q[idx]=%f, localMax.q[t]=%f max(pixels)=%f \n",
3250 dof = nMaxPads - 3 * nParameters + 1;
3251 double chi20 = chi2.first;
3252 double chi21 = chi2.second;
3268 criteriom = cWeight0 * sqrt(chi20 / ndof0) + cWeight1 * sqrt(chi21 / ndof1);
3274 " %2d %3d %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",
3275 macroIt, nParameters, chi20 + chi21, sqrt((chi20 + chi21) / dof),
3276 sqrt(chi20 / ndof0), sqrt(chi21 / ndof1),
3277 sqrt(chi20 / ndof0) + sqrt(chi21 / ndof1),
3278 cWeight0 * sqrt(chi20 / ndof0) + cWeight1 * sqrt(chi21 / ndof1));
3303 nPixels =
pixels->getNbrOfPads();
3305 Cij =
new double[nPads * nPixels];
3307 maskCij =
new Mask_t[nPads * nPixels];
3310 printf(
" min/max, %g, %g \n", vectorMin(
pixels->getCharges(), nPixels), vectorMax(
pixels->getCharges(), nPixels));
3312 (criteriom < 1.0 * previousCriteriom) && (macroIt < nMacroIterations);
3316 if (criteriom < 1.01 * previousCriteriom) {
3317 delete saveLocalMax;
3320 localMax = saveLocalMax;
3327 double cutRatio = 0.01;
3345 printf(
"seed selection: nbr Max parameters =%d, nLocMax=%d\n",
3348 "seed selection: Reduce the nbr of solutions to fit: Take %d/%d "
3356 const double* qLocalMax = localMax->
getCharges();
3358 [=](
int a,
int b) { return (qLocalMax[a] > qLocalMax[b]); });
3360 qCut = qLocalMax[
index[nMaxSolutions - 1]] - 1.e-03;
3368 " > seed selection: Final cut -> %d percent (qcut=%8.2f), number of "
3369 "local max removed = %d\n",
3370 int(cutRatio * 100), qCut, removedLocMax);
3375 int K = std::min(K0, nbrOfPadsInTheGroupCath);
3376 double*
w =
getW(thetaL, nbrOfPadsInTheGroupCath);
3377 double* muX =
getMuX(thetaL, nbrOfPadsInTheGroupCath);
3378 double* muY =
getMuY(thetaL, nbrOfPadsInTheGroupCath);
3379 double* varX =
getVarX(thetaL, nbrOfPadsInTheGroupCath);
3380 double* varY =
getVarY(thetaL, nbrOfPadsInTheGroupCath);
3382 const double* xl = localMax->
getX();
3383 const double* yl = localMax->
getY();
3384 const double* dxl = localMax->
getDX();
3385 const double* dyl = localMax->
getDY();
3386 for (
int k = 0; k < K; k++) {
3392 printf(
"k=%d XY=%f,%f varXY=%f,%f\n", k, muX[k], muY[k], varX[k], varY[k]);
3408void ClusterPEM::updateProjectionGroups()
3411 printf(
"> Update projected Groups [updateProjectionGroups]\n");
3414 Groups_t* cath0ToGrp = cathGroup[0];
3415 Groups_t* cath1ToGrp = cathGroup[1];
3420 vectorCopyShort(projPadToGrp, nProjPads, savePadGrp);
3422 for (
int k = 0; k < nProjPads; k++) {
3423 MapKToIJ_t ij = mapKToIJ[k];
3426 if ((
i > -1) && (
j == -1)) {
3428 projPadToGrp[k] = cath0ToGrp[
i];
3432 }
else if ((
i == -1) && (
j > -1)) {
3434 projPadToGrp[k] = cath1ToGrp[
j];
3438 }
else if ((
i > -1) && (
j > -1)) {
3440 projPadToGrp[k] = cath0ToGrp[
i];
3444 " [updateProjectionGroups] i, cath0ToGrp[i]=(%d, %d); j, "
3445 "cath1ToGrp[j]=(%d, %d)\n",
3446 i, cath0ToGrp[
i],
j, cath1ToGrp[
j]);
3447 throw std::overflow_error(
3448 "updateProjectionGroups cath0ToGrp[i] != cath1ToGrp[j]");
3453 throw std::overflow_error(
"updateProjectionGroups i,j=-1");
3461 for (
int p = 0; p < nProjPads; p++) {
3462 same = same && (projPadToGrp[p] == savePadGrp[p]);
3464 if (same ==
false) {
3475int ClusterPEM::laplacian2D(
const Pads& pads_,
PadIdx_t* neigh,
int chId,
3476 PadIdx_t* sortedLocalMax,
int kMax,
double* smoothQ)
3479 double eps = 1.0e-7;
3480 double noise = 4. * 0.22875;
3481 double laplacianCutOff = noise;
3484 int N = pads_.getNbrOfPads();
3485 const double*
x = pads_.getX();
3486 const double*
y = pads_.getY();
3487 const double* dx = pads_.getDX();
3488 const double* dy = pads_.getDY();
3489 const double* q = pads_.getCharges();
3495 vectorSetShort(unselected, 1, N);
3497 for (
int i = 0;
i < N;
i++) {
3499 double sumNeigh = 0;
3500 int nNeighSmaller = 0;
3504 for (
PadIdx_t* neigh_ptr = getTheFirtsNeighborOf(neigh,
i);
3505 *neigh_ptr != -1; neigh_ptr++) {
3509 nNeighSmaller += (q[
j] <= ((q[
i] + noise) * unselected[
j]));
3515 lapl[
i] =
float(nNeighSmaller) / nNeigh;
3516 if (lapl[
i] < laplacianCutOff) {
3519 unselected[
i] = (lapl[
i] != 1.0);
3520 smoothQ[
i] = sumNeigh / nNeigh;
3523 "Laplacian i=%d, x[i]=%6.3f, y[i]=%6.3f, z[i]=%6.3f, "
3524 "smoothQ[i]=%6.3f, lapl[i]=%6.3f\n",
3525 i,
x[
i],
y[
i], q[
i], smoothQ[
i], lapl[
i]);
3531 vectorBuildMaskEqual(lapl, 1.0, N, localMaxMask);
3535 int nSortedIdx = vectorGetIndexFromMask(localMaxMask, N, sortedLocalMax);
3541 std::sort(sortedLocalMax, &sortedLocalMax[nSortedIdx],
3542 [=](
int a,
int b) {
return q[
a] > q[
b]; });
3553 printf(
" [laplacian2D] (InspectModel) filtering Local Max\n");
3556 if ((nSortedIdx == 0) && (N != 0)) {
3559 printf(
"-> No local Max, take the highest value < 1\n");
3561 sortedLocalMax[0] = 0;
3570 double aspectRatio = 0;
3571 if ((N > 0) && (N < 6) && (chId <= 6)) {
3572 double xInf = DBL_MAX, xSup = DBL_MIN, yInf = DBL_MAX, ySup = DBL_MIN;
3574 for (
int i = 0;
i < N;
i++) {
3575 xInf = fmin(xInf,
x[
i] - dx[
i]);
3576 xSup = fmax(xSup,
x[
i] + dx[
i]);
3577 yInf = fmin(yInf,
y[
i] - dy[
i]);
3578 ySup = fmax(ySup,
y[
i] + dy[
i]);
3581 int nX =
int((xSup - xInf) / dx[0] + eps);
3583 int nY =
int((ySup - yInf) / dy[0] + eps);
3584 aspectRatio = fmin(nX, nY) / fmax(nX, nY);
3585 if (aspectRatio > 0.6) {
3590 " -> Limit to one local Max, nPads=%d, chId=%d, aspect ratio=%6.3f\n",
3591 N, chId, aspectRatio);
3598 if ((N > 0) && (q[sortedLocalMax[0]] > 2 * noise)) {
3599 int trunkIdx = nSortedIdx;
3600 for (
int ik = 0; ik < nSortedIdx; ik++) {
3601 if (q[sortedLocalMax[ik]] <= 2 * noise) {
3605 nSortedIdx = std::max(trunkIdx, 1);
3607 printf(
"-> Suppress %d local Max. too noisy (q < %6.3f),\n",
3608 nSortedIdx - trunkIdx, 2 * noise);
3628 if (nbrOfCathodePlanes != 2) {
3629 if (singleCathPlaneID == 0) {
3630 N0 = pads[0]->getNbrOfPads();
3632 N1 = pads[1]->getNbrOfPads();
3635 N0 = pads[0]->getNbrOfPads();
3636 N1 = pads[1]->getNbrOfPads();
3648 double smoothQ0[N0];
3649 double smoothQ1[N1];
3653 printf(
"> [findLocalMaxWithBothCathodes] N0=%d N1=%d\n", N0, N1);
3655 PadIdx_t* grpNeighborsCath0 =
nullptr;
3656 PadIdx_t* grpNeighborsCath1 =
nullptr;
3660 grpNeighborsCath0 = pads[0]->getFirstNeighbors();
3661 K0 = laplacian2D(*pads[0], grpNeighborsCath0, chamberId, localMax0, kMax0,
3665 grpNeighborsCath1 = pads[1]->getFirstNeighbors();
3666 K1 = laplacian2D(*pads[1], grpNeighborsCath1, chamberId, localMax1, kMax1,
3671 double localXMax[K0 + K1];
3672 double localYMax[K0 + K1];
3673 double localQMax[K0 + K1];
3677 vectorSetInt(mapIToGrpIdx, -1, N0);
3679 for (
int i = 0;
i < N0;
i++) {
3682 mapIToGrpIdx[
i] =
i;
3683 mapGrpIdxToI[
i] =
i;
3686 vectorSetInt(mapJToGrpIdx, -1, N1);
3688 for (
int j = 0;
j < N1;
j++) {
3691 mapJToGrpIdx[
j] =
j;
3692 mapGrpIdxToJ[
j] =
j;
3706 x0 = pads[0]->getX();
3707 y0 = pads[0]->getY();
3708 dx0 = pads[0]->getDX();
3709 dy0 = pads[0]->getDY();
3710 q0 = pads[0]->getCharges();
3713 x1 = pads[1]->getX();
3714 y1 = pads[1]->getY();
3715 dx1 = pads[1]->getDX();
3716 dy1 = pads[1]->getDY();
3717 q1 = pads[1]->getCharges();
3719 const double* xProj = projectedPads->
getX();
3720 const double* yProj = projectedPads->
getY();
3721 const double* dxProj = projectedPads->
getDX();
3722 const double* dyProj = projectedPads->
getDX();
3739 printf(
" Local max per cathode K0=%d, K1=%d\n", K0, K1);
3741 bool K0GreaterThanK1 = (K0 >= K1);
3742 bool K0EqualToK1 = (K0 == K1);
3744 bool highestLastLocalMax0;
3746 highestLastLocalMax0 =
false;
3747 }
else if (K1 == 0) {
3748 highestLastLocalMax0 =
true;
3752 highestLastLocalMax0 = (q0[localMax0[std::max(K0 - 1, 0)]] >=
3753 q1[localMax1[std::max(K1 - 1, 0)]]);
3759 const double *qU, *qV;
3762 const double *xu, *yu, *dxu, *dyu;
3763 const double *xv, *yv, *dxv, *dyv;
3764 const PadIdx_t *mapGrpIdxToU, *mapGrpIdxToV;
3765 PadIdx_t *mapUToGrpIdx, *mapVToGrpIdx;
3768 if (K0GreaterThanK1 || (K0EqualToK1 && highestLastLocalMax0)) {
3781 localMaxU = localMax0;
3782 localMaxV = localMax1;
3787 mapGrpIdxToU = mapGrpIdxToI;
3788 mapGrpIdxToV = mapGrpIdxToJ;
3789 mapUToGrpIdx = mapIToGrpIdx;
3790 mapVToGrpIdx = mapJToGrpIdx;
3805 localMaxU = localMax1;
3806 localMaxV = localMax0;
3811 mapGrpIdxToU = mapGrpIdxToJ;
3812 mapGrpIdxToV = mapGrpIdxToI;
3813 mapUToGrpIdx = mapJToGrpIdx;
3814 mapVToGrpIdx = mapIToGrpIdx;
3819 vectorSetShort(qvAvailable, 1, KV);
3825 printf(
" Local max combinatorics: KU=%d KV=%d\n", KU, KV);
3828 for (
int i = 0;
i < N0;
i++) {
3831 for (
int j = 0;
j < N1;
j++) {
3835 printf(
" %d inter %d, grp : %d inter %d yes=%d\n", ii, jj,
i,
j,
3836 mapIJToK[ii * N1 + jj]);
3840 for (
int u = 0; u < KU; u++) {
3843 double maxValue = 0.0;
3858 printf(
" Cathode u=%d localMaxU[u]=%d, x,y= %6.3f, %6.3f, q=%6.3f\n", u,
3859 localMaxU[u], xu[localMaxU[u]], yu[localMaxU[u]],
3863 for (
int v = 0;
v < KV;
v++) {
3870 interuv = (mapIJToK[vg * N1 + ug] != -1);
3875 interuv = (mapIJToK[ug * N1 + vg] != -1);
3878 double val = qV[vPadIdx] * qvAvailable[
v];
3879 if (
val > maxValue) {
3882 maxPadVIdx = vPadIdx;
3890 if (maxPadVIdx != -1) {
3894 int vg = mapGrpIdxToV[maxPadVIdx];
3896 kProj = mapIJToK[vg * N1 + ug];
3898 kProj = mapIJToK[ug * N1 + vg];
3901 localXMax[k] = xProj[kProj];
3902 localYMax[k] = yProj[kProj];
3904 localQMax[k] = qU[uPadIdx];
3906 qvAvailable[maxCathVIdx] = 0;
3909 " found intersection of u with v: u,v=(%d,%d) , x=%f, y=%f, "
3911 u, maxCathVIdx, localXMax[k], localYMax[k], localQMax[k]);
3929 " No intersection between u=%d and v-set of , approximate the "
3936 for (uInterV = interUV; uPad < ug; uInterV++) {
3937 if (*uInterV == -1) {
3944 if ((NV != 0) && (uInterV[0] != -1)) {
3945 double vMin = 1.e+06;
3946 double vMax = -1.e+06;
3948 if (dxu[u] < dyu[u]) {
3951 for (; *uInterV != -1; uInterV++) {
3952 PadIdx_t idx = mapVToGrpIdx[*uInterV];
3954 printf(
" Global upad=%d intersect global vpad=%d grpIdx=%d\n",
3955 uPad, *uInterV, idx);
3958 vMin = fmin(vMin, yv[idx] - dyv[idx]);
3959 vMax = fmax(vMax, yv[idx] + dyv[idx]);
3962 localXMax[k] = xu[uPadIdx];
3963 localYMax[k] = 0.5 * (vMin + vMax);
3964 localQMax[k] = qU[uPadIdx];
3965 if (localYMax[k] == 0 &&
3967 printf(
"WARNING localYMax[k] == 0, meaning no intersection");
3972 for (; *uInterV != -1; uInterV++) {
3973 PadIdx_t idx = mapVToGrpIdx[*uInterV];
3975 printf(
" Global upad=%d intersect global vpad=%d grpIdx=%d \n",
3976 uPad, *uInterV, idx);
3981 "xv[idx], yv[idx], dxv[idx], dyv[idx]: %6.3f %6.3f "
3983 xv[idx], yv[idx], dxv[idx], dyv[idx]);
3985 vMin = fmin(vMin, xv[idx] - dxv[idx]);
3986 vMax = fmax(vMax, xv[idx] + dxv[idx]);
3989 localXMax[k] = 0.5 * (vMin + vMax);
3990 localYMax[k] = yu[uPadIdx];
3991 localQMax[k] = qU[uPadIdx];
3993 if (localXMax[k] == 0 &&
3995 printf(
"WARNING localXMax[k] == 0, meaning no intersection");
4000 " solution found with all intersection of u=%d with all v, x "
4001 "more precise %d, position=(%f,%f), qU=%f\n",
4002 u, (dxu[u] < dyu[u]), localXMax[k], localYMax[k],
4013 localXMax[k] = xu[uPadIdx];
4014 localYMax[k] = yu[uPadIdx];
4015 localQMax[k] = qU[uPadIdx];
4018 " No intersection with u, u added in local Max: k=%d u=%d, "
4019 "position=(%f,%f), qU=%f\n",
4020 k, u, localXMax[k], localYMax[k], localQMax[k]);
4027 for (
int v = 0;
v < KV;
v++) {
4028 if (qvAvailable[
v]) {
4029 int l = localMaxV[
v];
4030 localXMax[k] = xv[l];
4031 localYMax[k] = yv[l];
4032 localQMax[k] = qV[l];
4035 " Remaining VMax, v added in local Max: v=%d, "
4036 "position=(%f,%f), qU=%f\n",
4037 v, localXMax[k], localYMax[k], localQMax[k]);
4043 double* varX =
getVarX(thetaOut, kMax);
4044 double* varY =
getVarY(thetaOut, kMax);
4045 double* muX =
getMuX(thetaOut, kMax);
4046 double* muY =
getMuY(thetaOut, kMax);
4047 double*
w =
getW(thetaOut, kMax);
4050 for (
int k_ = 0; k_ < k; k_++) {
4051 wRatio += localQMax[k_];
4053 wRatio = 1.0 / wRatio;
4055 printf(
"Local max found k=%d kmax=%d\n", k, kMax);
4057 for (
int k_ = 0; k_ < k; k_++) {
4058 muX[k_] = localXMax[k_];
4059 muY[k_] = localYMax[k_];
4060 w[k_] = localQMax[k_] * wRatio;
4062 printf(
" w=%6.3f, mux=%7.3f, muy=%7.3f\n",
w[k_], muX[k_], muY[k_]);
Clustering and fifting parameters.
Definition of a class to reconstruct clusters with the MLEM algorithm.
void inspectSavePixels(int which, o2::mch::Pads &pixels)
void saveProjPadToGroups(o2::mch::Groups_t *projPadToGrp, int N)
void inspectOverWriteQ(int which, const double *qPixels)
std::pair< int, int > getNxNy(int c)
const double * getCharges(int c)
int findLocalMaxWithBothCathodes(double *thetaOut, int kMax)
int findLocalMaxWithPEMFullRefinement(double *thetaL, int nbrOfPadsInTheGroupCath)
DataBlock_t fit(double *thetaInit, int K)
int buildProjectedGeometry(int includeAlonePads)
double * projectChargeOnProjGeometry(int includeAlonePads)
int getNbrOfPadsInGroup(int g)
int findLocalMaxWithPEM2Lev(double *thetaL, int nbrOfPadsInTheGroupCath)
std::pair< double, double > computeChargeBarycenter(int plane)
int findLocalMaxWithPEM(double *thetaL, int nbrOfPadsInTheGroupCath)
double getTotalCharge(int c)
const Pads * getPads(int c)
const double * getX() const
static void printNeighbors(const PadIdx_t *neigh, int N)
const double * getXSup() const
@ xydxdyMode
x, y, dx, dy pad coordinates
@ xyInfSupMode
xInf=x, xSup=dx, yInf=y, ySup=dy pad coordinates
void setCathodes(Mask_t cath_)
Pads * extractLocalMax(std::vector< PadIdx_t > &localMaxIdx, double dxMinPadSize, double dyMinPadSize)
static int getNbrOfPads(const Pads *pads)
const double * getDY() const
int addIsolatedPadInGroups(Mask_t *cathToGrp, Mask_t *grpToGrp, int nGroups)
const double * getCharges() const
const double * getYInf() const
const double * getY() const
int getNbrOfObsPads() const
const double * getXInf() const
PadIdx_t * getFirstNeighbors()
int removePads(double qCut)
const double * getYSup() const
static void printPads(const char *title, const Pads &pads)
const double * getDX() const
float sum(float s, o2::dcs::DataPointValue v)
GLint GLint GLsizei GLuint * counters
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint GLfloat GLfloat GLfloat x1
GLboolean GLboolean GLboolean b
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
GLboolean GLboolean GLboolean GLboolean a
GLubyte GLubyte GLubyte GLubyte w
GLuint GLfloat GLfloat y0
void vectorPrintShort(const char *str, const short *x, int K)
std::pair< int, double * > DataBlock_t
void maskedCopyTheta(const double *theta, int K, const Mask_t *mask, int nMask, double *maskedTheta, int maskedK)
double * getMuY(double *theta, int K)
void printTheta(const char *str, double meanCharge, const double *theta, int K)
void print_matrix(const gsl_matrix *m)
void computeFastCij(const Pads &pads, const Pads &pixel, double Cij[])
void printGSLVector(const char *str, const gsl_vector *v)
const double * getConstVarY(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)
double * getVarX(double *theta, int K)
void printMatrixShort(const char *str, const short *matrix, int N, int M)
void checkCij(const Pads &pads, const Pads &pixels, const double *checkCij, int mode)
double * getMuX(double *theta, int K)
double * getW(double *theta, int K)
void printInterMap(const char *str, const PadIdx_t *inter, int N)
const double * getConstMuX(const double *theta, int K)
double * getVarY(double *theta, int K)
void deleteShort(short *ptr)
const double * getConstMuY(const double *theta, int K)
ClusterConfig clusterConfig
gsl_matrix * moore_penrose_pinv(gsl_matrix *A, double rcond)
const double * getConstVarX(const double *theta, int K)
std::pair< double, double > PoissonEMLoop(const Pads &pads, Pads &pixels, const double *Cij, Mask_t *maskCij, int qCutMode, double minPadError, int nItMax)
void fitMathieson(const Pads &iPads, double *thetaInit, int kInit, int dimOfParameters, int axe, int mode, double *thetaFinal, double *khi2, double *pError)
void printMatrixChar(const char *str, const char *matrix, int N, int M)
void vectorPrintInt(const char *str, const int *x, int K)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
double minChargeOfClusterPerCathode
@ active
Describe default activation.
ActivateMode inspectModel
VerboseMode EMLocalMaxLog
VerboseMode laplacianLocalMaxLog
@ info
Describes main steps and high level behaviors.
@ detail
Describes in detail.
int nbrOfPadsLimitForTheFitting
VerboseMode processingLog
VerboseMode padMappingLog