Project
Loading...
Searching...
No Matches
mathiesonFit.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <cstdio>
13#include <gsl/gsl_multifit_nlin.h>
14#include <gsl/gsl_version.h>
16#include "mathUtil.h"
17#include "mathieson.h"
18#include "mathiesonFit.h"
19
20namespace o2
21{
22namespace mch
23{
25}
26} // namespace o2
27
28using namespace o2::mch;
29
31
32double chargeNormalization(const Mask_t* cath, const Mask_t* notSaturated, const double* cathMaxObs, int N, double* z, double* coefNorm)
33{
34 double zMax[2] = {0, 0};
35 for (int i = 0; i < N; i++) {
36 zMax[cath[i]] = std::fmax(zMax[cath[i]], notSaturated[i] * z[i]);
37 }
38 // Avoid dividing by 0
39 for (int c = 0; c < 2; c++) {
40 if (zMax[c] < 1.0e-6) {
41 // In this case cathMax[c] must be 0
42 zMax[c] = 1.0;
43 }
44 }
45 //
46 // Normalization coefficient
47 //
48 // Use the max charge cathode for each cathode
49 coefNorm[0] = cathMaxObs[0] / zMax[0];
50 coefNorm[1] = cathMaxObs[1] / zMax[1];
51 // Perform the normalization
52 for (int i = 0; i < N; i++) {
53 z[i] = z[i] * coefNorm[cath[i]];
54 // To have traces about the fitting
55 // chargePerCath[cath[i]] += z[i];
56 }
57 // printf(" cathMaxObs??? %f %f \n", cathMaxObs[0], cathMaxObs[1] );
58 // printf("coefNorm ??? %f %f \n", coefNorm[0], coefNorm[1] );
59 // Use to weight the penalization
60 double meanCoef = (coefNorm[0] + coefNorm[1]) /
61 ((coefNorm[0] > 1.0e-6) + (coefNorm[1] > 1.0e-6));
62
64 printf(
65 " Max of unsaturated (observed) pads (cathMax0/1)= %f, %f, "
66 "maxThZ (computed) %f, %f\n",
67 cathMaxObs[0], cathMaxObs[1], zMax[0], zMax[1]);
68 }
69
70 return meanCoef;
71}
72
73int f_ChargeIntegral(const gsl_vector* gslParams, void* dataFit,
74 gsl_vector* residuals)
75{
77 int N = dataPtr->N;
78 int K = dataPtr->K;
79 const double* xInf = dataPtr->xInf_ptr;
80 const double* yInf = dataPtr->yInf_ptr;
81 const double* xSup = dataPtr->xSup_ptr;
82 const double* ySup = dataPtr->ySup_ptr;
83 const Mask_t* cath = dataPtr->cath_ptr;
84 const double* zObs = dataPtr->zObs_ptr;
85 Mask_t* notSaturated = dataPtr->notSaturated_ptr;
86 int chamberId = dataPtr->chamberId;
87 double* cathWeights = dataPtr->cathWeights_ptr;
88 double* cathMax = dataPtr->cathMax_ptr;
89 double* zCathTotalCharge = dataPtr->zCathTotalCharge_ptr;
90 double* cathCoefNorm = dataPtr->cathCoefNorm_ptr;
91 int dimOfParameters = dataPtr->dimOfParameters;
92 int axe = dataPtr->axe;
93
94 // printf(" dimOfParameters, axe: %d %d\n", dimOfParameters, axe);
95 // ??? int verbose = dataPtr->verbose;
96 // Parameters
97 const double* params = gsl_vector_const_ptr(gslParams, 0);
98 // Note:
99 // mux = mu[0:K-1]
100 // muy = mu[K:2K-1]
101 const double* mu = &params[0];
102 // ??? inv double* w = (double*)&params[2 * K];
103 double* w = (double*)&params[(dimOfParameters - 1) * K];
104
105 // Set constrain: sum_(w_k) = 1
106 double lastW = 1.0 - vectorSum(w, K - 1);
107 //
108 // Display paramameters (w, mu_x, mu_x
110 printf(" Function evaluation at:\n");
111 for (int k = 0; k < K; k++) {
112 if (dimOfParameters == 3) {
113 printf(" mu_k[%d] = %g %g \n", k, mu[k], mu[K + k]);
114 } else {
115 printf(" mu_k[%d] = %g \n", k, mu[k]);
116 }
117 }
118 for (int k = 0; k < K - 1; k++) {
119 printf(" w_k[%d] = %g \n", k, w[k]);
120 }
121 // Last W
122 printf(" w_k[%d] = %g \n", K - 1, lastW);
123 }
124
125 // Charge Integral on Pads
126 double z[N];
127 vectorSetZero(z, N);
128 double zTmp[N];
129 //
130 double xyInf0[N];
131 double xySup0[N];
132 /*
133 double* xInf = getXInf(xyInfSup, N);
134 double* xSup = getXSup(xyInfSup, N);
135 double* yInf = getYInf(xyInfSup, N);
136 double* ySup = getYSup(xyInfSup, N);
137 */
138 // Compute the pads charge considering the
139 // Mathieson set w_k, mu_x, mu_y
140 // TODO: Minor optimization avoid to
141 // compute x[:] - dx[:] i.E use xInf / xSup
142 for (int k = 0; k < K; k++) {
143 if (axe == 0) {
144 // xInf[:] = x[:] - dx[:] - muX[k]
145 // Inv vectorAddVector(x, -1.0, dx, N, xInf);
146 vectorAddScalar(xInf, -mu[k], N, xyInf0);
147 vectorAddScalar(xSup, -mu[k], N, xySup0);
148 // xSup = xInf + 2.0 * dxy[0]
149 // Inv vectorAddVector(xInf, 2.0, dx, N, xSup);
150 // yInf = xy[1] - dxy[1] - mu[k,1]
151 // ySup = yInf + 2.0 * dxy[1]
152 // vectorAddScalar(xSup, -mu[k], N, xSup);
153 compute1DPadIntegrals(xyInf0, xySup0, N, 0, chamberId, zTmp);
154 // Unnecessary to multiply by a cst (y integral part)
155 // vectorMultScal( xIntegrals, yCstIntegral, N, Integrals);
156 } else if (axe == 1) {
157
158 /*
159 vectorAddVector(y, -1.0, dy, N, yInf);
160 // Take care : not -mu[K + k] for muy
161 vectorAddScalar(yInf, -mu[k], N, yInf);
162 // ySup = yInf + 2.0 * dxy[0]
163 vectorAddVector(yInf, 2.0, dy, N, ySup);
164 */
165 vectorAddScalar(yInf, -mu[K + k], N, xyInf0);
166 vectorAddScalar(xSup, -mu[K + k], N, xySup0);
167 compute1DPadIntegrals(xyInf0, xySup0, N, 1, chamberId, zTmp);
168 // Unnecessary to multiply by a cst (x integral part)
169 } else {
170 // xInf[:] = x[:] - dx[:] - muX[k]
171 /*
172 vectorAddVector(x, -1.0, dx, N, xInf);
173 vectorAddScalar(xInf, -mu[k], N, xInf);
174 // xSup = xInf + 2.0 * dxy[0]
175 vectorAddVector(xInf, 2.0, dx, N, xSup);
176 // yInf = xy[1] - dxy[1] - mu[k,1]
177 // ySup = yInf + 2.0 * dxy[1]
178 vectorAddVector(y, -1.0, dy, N, yInf);
179 vectorAddScalar(yInf, -mu[K + k], N, yInf);
180 // ySup = yInf + 2.0 * dxy[0]
181 vectorAddVector(yInf, 2.0, dy, N, ySup);
182 */
183 computeCompressed2DPadIntegrals(dataPtr->compressedPads, mu[k], mu[K + k], N, chamberId, zTmp);
184 }
185 //
186 // Multiply by the weight w[k]
187 double wTmp = (k != K - 1) ? w[k] : lastW;
188 vectorAddVector(z, wTmp, zTmp, N, z);
189 }
190 // ??? vectorPrint("zObs", zObs, N);
191
192 //
193 // To Normalize each cathode with the charge sum
194 // of unsaturated pads
195 // NOT USED in this residual computation
196 double sumNormalizedZ[2];
198 for (int i = 0; i < N; i++) {
199 if (cath[i] == 0) {
200 sumNormalizedZ[0] += notSaturated[i] * z[i];
201 } else {
202 sumNormalizedZ[1] += notSaturated[i] * z[i];
203 }
204 }
205 }
206
207 // Charge normalization
208 // Get the max charge of unsaturated pads for each cathodes
209 double meanCoef = chargeNormalization(cath, notSaturated, cathMax, N, z, cathCoefNorm);
210
211 //
212 // printf("maxCath: %f %f\n", cathMax[0], cathMax[1]);
213 // printf("coefNorm: %f %f\n", coefNorm[0], coefNorm[1]);
214 // printf("meaCoef: %f \n", meanCoef);
215 //
216
217 //
218 // Cathode Penalization
219 //
220 // Consider the charge sum for each cathode
221 // Tested but NOT USED
222 // To be removed for perf
223 double chargePerCath[2] = {0., 0.};
224 for (int i = 0; i < N; i++) {
225 // To have traces about the fitting
226 chargePerCath[cath[i]] += z[i];
227 }
228 double cathPenal = 0;
230 cathPenal = fabs(zCathTotalCharge[0] - chargePerCath[0]) +
231 fabs(zCathTotalCharge[1] - chargePerCath[1]);
232 }
233
234 //
235 // w-Penalization
236 //
237 // Each w, must be 0 < w < 1
238 double wPenal = 0.0;
239 for (int k = 0; k < (K - 1); k++) {
240 if (w[k] < 0.0) {
241 wPenal += (-w[k]);
242 } else if (w[k] > 1.0) {
243 wPenal += (w[k] - 1.0);
244 }
245 }
246 // ... and the w-sum must be equal to 1
247 wPenal = wPenal + fabs(1.0 - vectorSum(w, K - 1) - lastW);
249 printf(" wPenal: %f\n", wPenal);
250 }
251 // Compute residual
252 for (int i = 0; i < N; i++) {
253 // Don't consider saturated pads (notSaturated[i] = 0)
254 double mask = notSaturated[i];
255 if ((notSaturated[i] == 0) && (z[i] < zObs[i])) {
256 // Except those charge < Observed charge
257 mask = 1.0;
258 }
259 //
260 // Residuals with penalization
261 //
262 gsl_vector_set(residuals, i, mask * ((z[i] - zObs[i]) + meanCoef * wPenal));
263 //
264 // Without penalization
265 // gsl_vector_set(residuals, i, mask * (zObs[i] - z[i]) + 0 * wPenal);
266 //
267 // Other studied penalization
268 // gsl_vector_set(residuals, i, (zObs[i] - z[i]) * (1.0 + cathPenal) +
269 // wPenal);
270 }
272 printf(" Observed sumCath0=%15.8f, sumCath1=%15.8f,\n",
273 zCathTotalCharge[0], zCathTotalCharge[1]);
274 // printf(" fitted sumCath0=%15.8f, sumCath1=%15.8f,\n", chargePerCath,
275 // chargePerCath);
276 printf(" Penalties cathPenal=%5.4g wPenal=%5.4g \n", 1.0 + cathPenal,
277 wPenal);
278 printf(" Residues\n");
279 printf(" %15s %15s %15s %15s %15s %15s\n", "zObs", "z", "cathWeight",
280 "norm. factor", "notSaturated", "residual");
281 for (int i = 0; i < N; i++) {
282 printf(" %15.8f %15.8f %15.8f %15.8f %d %15.8f\n", zObs[i],
283 z[i], cathWeights[i], sumNormalizedZ[cath[i]] * cathWeights[i],
284 notSaturated[i], gsl_vector_get(residuals, i));
285 }
286 printf("\n");
287 }
289 printf(" |f| = %g \n", gsl_blas_dnrm2(residuals));
290 }
291 /*
292 for (int i = 0; i < N; i++) {
293 printf("%f ", gsl_vector_get(residuals, i));
294 }
295 printf("\n");
296 */
297 // char str[16];
298 // scanf( "%s", str);
299 // printf(" norm cst meanCoef=%f, wPenal=%f \n", meanCoef, wPenal);
300 return GSL_SUCCESS;
301}
302/*
303int f_ChargeIntegralBeforeCompressVersion(const gsl_vector* gslParams, void* dataFit,
304 gsl_vector* residuals)
305{
306 funcDescription_t* dataPtr = (funcDescription_t*)dataFit;
307 int N = dataPtr->N;
308 int K = dataPtr->K;
309 const double* x = dataPtr->x_ptr;
310 const double* y = dataPtr->y_ptr;
311 const double* dx = dataPtr->dx_ptr;
312 const double* dy = dataPtr->dy_ptr;
313 const Mask_t* cath = dataPtr->cath_ptr;
314 const double* zObs = dataPtr->zObs_ptr;
315 Mask_t* notSaturated = dataPtr->notSaturated_ptr;
316 int chamberId = dataPtr->chamberId;
317 double* cathWeights = dataPtr->cathWeights_ptr;
318 double* cathMax = dataPtr->cathMax_ptr;
319 double* zCathTotalCharge = dataPtr->zCathTotalCharge_ptr;
320 double* cathCoefNorm = dataPtr->cathCoefNorm_ptr;
321 int dimOfParameters = dataPtr->dimOfParameters;
322 int axe = dataPtr->axe;
323
324 // printf(" dimOfParameters, axe: %d %d\n", dimOfParameters, axe);
325 // ??? int verbose = dataPtr->verbose;
326 // Parameters
327 const double* params = gsl_vector_const_ptr(gslParams, 0);
328 // Note:
329 // mux = mu[0:K-1]
330 // muy = mu[K:2K-1]
331 const double* mu = &params[0];
332 // ??? inv double* w = (double*)&params[2 * K];
333 double* w = (double*)&params[ (dimOfParameters - 1) * K];
334
335 // Set constrain: sum_(w_k) = 1
336 double lastW = 1.0 - vectorSum(w, K - 1);
337 //
338 // Display paramameters (w, mu_x, mu_x
339 if (clusterConfig.fittingLog >= clusterConfig.detail) {
340 printf(" Function evaluation at:\n");
341 for (int k = 0; k < K; k++) {
342 if (dimOfParameters==3) {
343 printf(" mu_k[%d] = %g %g \n", k, mu[k], mu[K + k]);
344 } else {
345 printf(" mu_k[%d] = %g \n", k, mu[k]);
346 }
347 }
348 for (int k = 0; k < K - 1; k++) {
349 printf(" w_k[%d] = %g \n", k, w[k]);
350 }
351 // Last W
352 printf(" w_k[%d] = %g \n", K - 1, lastW);
353 }
354
355 // Charge Integral on Pads
356 double z[N];
357 vectorSetZero(z, N);
358 double zTmp[N];
359 //
360 double xyInfSup[4 * N];
361 double* xInf = getXInf(xyInfSup, N);
362 double* xSup = getXSup(xyInfSup, N);
363 double* yInf = getYInf(xyInfSup, N);
364 double* ySup = getYSup(xyInfSup, N);
365
366 // Compute the pads charge considering the
367 // Mathieson set w_k, mu_x, mu_y
368 // TODO: Minor optimization avoid to
369 // compute x[:] - dx[:] i.E use xInf / xSup
370 for (int k = 0; k < K; k++) {
371 if (axe == 0) {
372 // xInf[:] = x[:] - dx[:] - muX[k]
373 vectorAddVector(x, -1.0, dx, N, xInf);
374 vectorAddScalar(xInf, -mu[k], N, xInf);
375 // xSup = xInf + 2.0 * dxy[0]
376 vectorAddVector(xInf, 2.0, dx, N, xSup);
377 // yInf = xy[1] - dxy[1] - mu[k,1]
378 // ySup = yInf + 2.0 * dxy[1]
379 compute1DPadIntegrals( xInf, xSup, N, 0, chamberId, zTmp);
380 // Unnecessary to multiply by a cst (y integral part)
381 // vectorMultScal( xIntegrals, yCstIntegral, N, Integrals);
382 } else if (axe == 1) {
383 vectorAddVector(y, -1.0, dy, N, yInf);
384 // Take care : not -mu[K + k] for muy
385 vectorAddScalar(yInf, -mu[k], N, yInf);
386 // ySup = yInf + 2.0 * dxy[0]
387 vectorAddVector(yInf, 2.0, dy, N, ySup);
388 compute1DPadIntegrals( yInf, ySup, N, 1, chamberId, zTmp);
389 // Unnecessary to multiply by a cst (x integral part)
390 } else {
391 // xInf[:] = x[:] - dx[:] - muX[k]
392 vectorAddVector(x, -1.0, dx, N, xInf);
393 vectorAddScalar(xInf, -mu[k], N, xInf);
394 // xSup = xInf + 2.0 * dxy[0]
395 vectorAddVector(xInf, 2.0, dx, N, xSup);
396 // yInf = xy[1] - dxy[1] - mu[k,1]
397 // ySup = yInf + 2.0 * dxy[1]
398 vectorAddVector(y, -1.0, dy, N, yInf);
399 vectorAddScalar(yInf, -mu[K + k], N, yInf);
400 // ySup = yInf + 2.0 * dxy[0]
401 vectorAddVector(yInf, 2.0, dy, N, ySup);
402 compute2DPadIntegrals(xInf, xSup, yInf, ySup, N, chamberId, zTmp);
403 }
404 //
405 // Multiply by the weight w[k]
406 double wTmp = (k != K - 1) ? w[k] : lastW;
407 vectorAddVector(z, wTmp, zTmp, N, z);
408 }
409 // ??? vectorPrint("zObs", zObs, N);
410
411 //
412 // To Normalize each cathode with the charge sum
413 // of unsaturated pads
414 // NOT USED in this residual computation
415 double sumNormalizedZ[2];
416 if (clusterConfig.fittingLog >= clusterConfig.debug) {
417 for (int i = 0; i < N; i++) {
418 if (cath[i] == 0) {
419 sumNormalizedZ[0] += notSaturated[i] * z[i];
420 } else {
421 sumNormalizedZ[1] += notSaturated[i] * z[i];
422 }
423 }
424 }
425
426 // Charge normalization
427 // Get the max charge of unsaturated pads for each cathodes
428 double meanCoef = chargeNormalization( cath, notSaturated, cathMax, N, z, cathCoefNorm );
429
430 //
431 // printf("maxCath: %f %f\n", cathMax[0], cathMax[1]);
432 // printf("coefNorm: %f %f\n", coefNorm[0], coefNorm[1]);
433 // printf("meaCoef: %f \n", meanCoef);
434 //
435
436 //
437 // Cathode Penalization
438 //
439 // Consider the charge sum for each cathode
440 // Tested but NOT USED
441 // To be removed for perf
442 double chargePerCath[2] = {0., 0.};
443 for (int i = 0; i < N; i++) {
444 // To have traces about the fitting
445 chargePerCath[cath[i]] += z[i];
446 }
447 double cathPenal = 0;
448 if (clusterConfig.fittingLog >= clusterConfig.debug) {
449 cathPenal = fabs(zCathTotalCharge[0] - chargePerCath[0]) +
450 fabs(zCathTotalCharge[1] - chargePerCath[1]);
451 }
452
453 //
454 // w-Penalization
455 //
456 // Each w, must be 0 < w < 1
457 double wPenal = 0.0;
458 for (int k = 0; k < (K - 1); k++) {
459 if (w[k] < 0.0) {
460 wPenal += (-w[k]);
461 } else if (w[k] > 1.0) {
462 wPenal += (w[k] - 1.0);
463 }
464 }
465 // ... and the w-sum must be equal to 1
466 wPenal = wPenal + fabs(1.0 - vectorSum(w, K - 1) - lastW);
467 if (clusterConfig.fittingLog >= clusterConfig.debug) {
468 printf(" wPenal: %f\n", wPenal);
469 }
470 // Compute residual
471 for (int i = 0; i < N; i++) {
472 // Don't consider saturated pads (notSaturated[i] = 0)
473 double mask = notSaturated[i];
474 if ((notSaturated[i] == 0) && (z[i] < zObs[i])) {
475 // Except those charge < Observed charge
476 mask = 1.0;
477 }
478 //
479 // Residuals with penalization
480 //
481 gsl_vector_set(residuals, i, mask * ((z[i] - zObs[i]) + meanCoef * wPenal));
482 //
483 // Without penalization
484 // gsl_vector_set(residuals, i, mask * (zObs[i] - z[i]) + 0 * wPenal);
485 //
486 // Other studied penalization
487 // gsl_vector_set(residuals, i, (zObs[i] - z[i]) * (1.0 + cathPenal) +
488 // wPenal);
489 }
490 if (clusterConfig.fittingLog >= clusterConfig.debug) {
491 printf(" Observed sumCath0=%15.8f, sumCath1=%15.8f,\n",
492 zCathTotalCharge[0], zCathTotalCharge[1]);
493 // printf(" fitted sumCath0=%15.8f, sumCath1=%15.8f,\n", chargePerCath,
494 // chargePerCath);
495 printf(" Penalties cathPenal=%5.4g wPenal=%5.4g \n", 1.0 + cathPenal,
496 wPenal);
497 printf(" Residues\n");
498 printf(" %15s %15s %15s %15s %15s %15s\n", "zObs", "z", "cathWeight",
499 "norm. factor", "notSaturated", "residual");
500 for (int i = 0; i < N; i++) {
501 printf(" %15.8f %15.8f %15.8f %15.8f %d %15.8f\n", zObs[i],
502 z[i], cathWeights[i], sumNormalizedZ[cath[i]] * cathWeights[i],
503 notSaturated[i], gsl_vector_get(residuals, i));
504 }
505 printf("\n");
506 }
507 if (clusterConfig.fittingLog >= clusterConfig.detail) {
508 printf(" |f| = %g \n", gsl_blas_dnrm2(residuals));
509 }
510 // char str[16];
511 // scanf( "%s", str);
512 // printf(" norm cst meanCoef=%f, wPenal=%f \n", meanCoef, wPenal);
513 return GSL_SUCCESS;
514}
515*/
516
517/*
518// Derivate of the Charge Integral i.e. mathieson
519int df_ChargeIntegral(const gsl_vector* gslParams, void* dataFit,
520 gsl_matrix* J)
521{
522 funcDescription_t* dataPtr = (funcDescription_t*)dataFit;
523 int N = dataPtr->N;
524 int K = dataPtr->K;
525 const double* x = dataPtr->x_ptr;
526 const double* y = dataPtr->y_ptr;
527 const double* dx = dataPtr->dx_ptr;
528 const double* dy = dataPtr->dy_ptr;
529 const Mask_t* cath = dataPtr->cath_ptr;
530 const double* zObs = dataPtr->zObs_ptr;
531 Mask_t* notSaturated = dataPtr->notSaturated_ptr;
532 int chamberId = dataPtr->chamberId;
533 double* cathWeights = dataPtr->cathWeights_ptr;
534 double* cathMax = dataPtr->cathMax_ptr;
535 double* zCathTotalCharge = dataPtr->zCathTotalCharge_ptr;
536 double* cathCoefNorm = dataPtr->cathCoefNorm_ptr;
537 // ??? int verbose = dataPtr->verbose;
538 // Parameters
539 const double* params = gsl_vector_const_ptr(gslParams, 0);
540 // Note:
541 // mux = mu[0:K-1]
542 // muy = mu[K:2K-1]
543 const double* mux = &params[0];
544 const double* muy = &params[K];
545 double* w = (double*)&params[2 * K];
546
547 // Compute mathieson on x/y
548 // and charge integral on x/y
549 double xCI[N], yCI[N];
550 double xMath[N], yMath[N], xyMath[N];
551 double xyInf[N], xySup[N];
552 double xyVar[N];
553 // Set constrain: sum_(w_k) = 1
554 double lastW = 1.0 - vectorSum(w, K - 1);
555
556 if (clusterConfig.fittingLog >= clusterConfig.detail) {
557 printf(" df evaluation at:\n");
558 for (int k = 0; k < K; k++) {
559 printf(" mu_k[%d] = %g %g \n", k, mux[k], muy[k]);
560 }
561 for (int k = 0; k < K - 1; k++) {
562 printf(" w_k[%d] = %g \n", k, w[k]);
563 }
564 // Last W
565 printf(" w_k[%d] = %g \n", K - 1, lastW);
566 }
567
568 for (int k = 0; k < K; k++) {
569 double w_k = (k < (K-1))? w[k]: lastW;
570 //
571 // X components for CI and mathieson
572 //
573 // xyVar = x - mux[k]
574 vectorAddScalar(x, -mux[k], N, xyVar);
575 // xInf = xyVar - dx
576 vectorAddVector(xyVar, -1.0, dx, N, xyInf);
577 // xSup = xInf + 2.0 * dx
578 vectorAddVector(xyInf, 2.0, dx, N, xySup);
579 // Compute the derivate : mathieson(xSup) - mathieson(xInf)
580 compute1DMathieson( xyInf, N, 0, chamberId, xyMath);
581 compute1DMathieson( xySup, N, 0, chamberId, xMath);
582 vectorAddVector( xMath, -1, xyMath, N, xMath);
583 vectorMultScalar(xMath, 4, N, xMath);
584 // Compute the 1D Charge integral on x
585 compute1DPadIntegrals(xyInf, xySup, N, 0, chamberId, xCI);
586 //
587 // Y components for CI and mathieson
588 //
589 // xyVar = y - muy[k]
590 vectorAddScalar(y, -muy[k], N, xyVar);
591 // Mathieson at xyVar
592 compute1DMathieson( xyVar, N, 1, chamberId, yMath);
593 // yInf = xyVar - dy
594 vectorAddVector(xyVar, -1.0, dy, N, xyInf);
595 // ySup = yInf + 2.0 * dy
596 vectorAddVector(xyInf, 2.0, dy, N, xySup);
597 // Compute the derivate : mathieson(ySup) - mathieson(yInf)
598 compute1DMathieson( xyInf, N, 1, chamberId, xyMath);
599 compute1DMathieson( xySup, N, 1, chamberId, yMath);
600 vectorAddVector( yMath, -1, xyMath, N, yMath);
601 vectorMultScalar(yMath, 4, N, yMath);
602 // Compute the 1D Charge integral on y
603 compute1DPadIntegrals(xyInf, xySup, N, 1, chamberId, yCI);
604
605 // Normalization factor
606 // double meanCoef = chargeNormalization( cath, notSaturated, cathMax, N, z);
607 //
608 // Jacobian matrix
609 //
610 // d / dmux_k component
611
612 for (int i = 0; i < N; i++) {
613 gsl_matrix_set (J, i, k, -0.5*w_k*cathCoefNorm[cath[i]]*xMath[i]*yCI[i]);
614 }
615 // d / dmuy_k component
616 for (int i = 0; i < N; i++) {
617 gsl_matrix_set (J, i, k+K, -0.5*w_k*cathCoefNorm[cath[i]]*xCI[i]*yMath[i]);
618 }
619 // d / dw_k component
620 if (k < K-1) {
621 for (int i = 0; i < N; i++) {
622 gsl_matrix_set (J, i, 2*K+k, -0.5*cathCoefNorm[cath[i]]*xCI[i]*yCI[i]);
623 }
624 }
625 // ??? vectorPrint("xMath", xMath, N);
626 // vectorPrint("yMath", yMath, N);
627 // vectorPrint("xCI", xCI, N);
628 // vectorPrint("yCI", yCI, N);
629 }
630 if (clusterConfig.fittingLog >= clusterConfig.detail) {
631 double sumdParam[3*K];
632 vectorSet( sumdParam, 0.0, 3*K);
633 for (int k=0; k < 3*K - 1; k++) {
634 printf("%2d: ", k);
635 for (int i=0; i < N; i++) {
636 sumdParam[k] += gsl_matrix_get( J, i, k);
637 printf("%g ", gsl_matrix_get(J, i, k) );
638 }
639 printf("\n");
640 }
641 printf(" Sum_i d/dparam :\n");
642 for (int k = 0; k < K; k++) {
643 printf(" mux/y[%d] = %g %g \n", k, sumdParam[k], sumdParam[K + k]);
644 }
645 for (int k = 0; k < K; k++) {
646 printf(" w_k[%d] = %g \n", k, sumdParam[2*K + k]);
647 }
648 }
649 return GSL_SUCCESS;
650}
651*/
652
653/*
654// Invalid version
655int f_ChargeIntegral0(const gsl_vector* gslParams, void* dataFit,
656 gsl_vector* residuals)
657{
658 funcDescription_t* dataPtr = (funcDescription_t*)dataFit;
659 int N = dataPtr->N;
660 int K = dataPtr->K;
661 const double* x = dataPtr->x_ptr;
662 const double* y = dataPtr->y_ptr;
663 const double* dx = dataPtr->dx_ptr;
664 const double* dy = dataPtr->dy_ptr;
665 const Mask_t* cath = dataPtr->cath_ptr;
666 const double* zObs = dataPtr->zObs_ptr;
667 const Mask_t* notSaturated = dataPtr->notSaturated_ptr;
668 int chamberId = dataPtr->chamberId;
669 double* cathWeights = dataPtr->cathWeights_ptr;
670 double* cathMax = dataPtr->cathMax_ptr;
671 double* zCathTotalCharge = dataPtr->zCathTotalCharge_ptr;
672 int verbose = dataPtr->verbose;
673 // Parameters
674 const double* params = gsl_vector_const_ptr(gslParams, 0);
675 // Note:
676 // mux = mu[0:K-1]
677 // muy = mu[K:2K-1]
678 const double* mu = &params[0];
679 double* w = (double*)&params[2 * K];
680
681 // Set constrain: sum_(w_k) = 1
682 // Rewriten ??? w[K-1] = 1.0 - vectorSum( w, K-1 );
683 double lastW = 1.0 - vectorSum(w, K - 1);
684 if (verbose > 1) {
685 printf(" Function evaluation at:\n");
686 for (int k = 0; k < K; k++) {
687 printf(" mu_k[%d] = %g %g \n", k, mu[k], mu[K + k]);
688 }
689 for (int k = 0; k < K - 1; k++) {
690 printf(" w_k[%d] = %g \n", k, w[k]);
691 }
692 // Last W
693 printf(" w_k[%d] = %g \n", K - 1, lastW);
694 }
695 int i;
696
697 // Charge Integral on Pads
698 double z[N];
699 // Not used
700 double z_k[N];
701 double zTmp[N];
702 // TODO: optimize compute before
703 double xyInfSup[4 * N];
704 //
705 double* xInf = getXInf(xyInfSup, N);
706 double* xSup = getXSup(xyInfSup, N);
707 double* yInf = getYInf(xyInfSup, N);
708 double* ySup = getYSup(xyInfSup, N);
709
710 vectorSetZero(z, N);
711 for (int k = 0; k < K; k++) {
712 // xInf[:] = x[:] - dx[:] - muX[k]
713 vectorAddVector(x, -1.0, dx, N, xInf);
714 vectorAddScalar(xInf, -mu[k], N, xInf);
715 // xSup = xInf + 2.0 * dxy[0]
716 vectorAddVector(xInf, 2.0, dx, N, xSup);
717 // yInf = xy[1] - dxy[1] - mu[k,1]
718 // ySup = yInf + 2.0 * dxy[1]
719 vectorAddVector(y, -1.0, dy, N, yInf);
720 vectorAddScalar(yInf, -mu[K + k], N, yInf);
721 // ySup = yInf + 2.0 * dxy[0]
722 vectorAddVector(yInf, 2.0, dy, N, ySup);
723 //
724 // z[:] += w[k] * cathWeight
725 // * computeMathieson2DIntegral( xInf[:], xSup[:], yInf[:], ySup[:], N
726 // )
727 // Inv. ??? compute2DPadIntegrals(xyInfSup, N, chamberId, zTmp);
728 compute2DPadIntegrals(xInf, xSup, yInf, ySup, N, chamberId, zTmp);
729 // GG Note: if require compute the charge of k-th component
730 // z_k[k] = vectorSum( zTmp, N )
731 // Done after the loop: vectorMultVector( zTmp, cathWeights, N, zTmp);
732 double wTmp = (k != K - 1) ? w[k] : lastW;
733 // saturated pads
734 // ??? ?
735 // vectorMaskedMult( zTmp, notSaturated, N, zTmp);
736 vectorAddVector(z, wTmp, zTmp, N, z);
737 }
738 // Normalize each cathodes
739 double sumNormalizedZ[2];
740 for (int i = 0; i < N; i++) {
741 if (cath[i] == 0) {
742 sumNormalizedZ[0] += notSaturated[i] * z[i];
743 } else {
744 sumNormalizedZ[1] += notSaturated[i] * z[i];
745 }
746 }
747 if (0) {
748 // Normalize with the charge sum
749 double var[2] = {1.0 / sumNormalizedZ[0], 1. / sumNormalizedZ[1]};
750 for (int i = 0; i < N; i++) {
751 if (cath[i] == 0) {
752 z[i] = z[i] * var[0];
753 } else {
754 z[i] = z[i] * var[1];
755 }
756 }
757 if (verbose > 1) {
758 printf(" sum mathiesons %f %f\n", sumNormalizedZ[0], sumNormalizedZ[1]);
759 }
760 vectorMultVector(z, cathWeights, N, z);
761 // vectorMultScalar( z, 2.0/sumNormalizedZ, N, z);
762
763 } else {
764 // Normalize with the max
765 double maxThZ[2];
766 for (int i = 0; i < N; i++) {
767 maxThZ[cath[i]] = fmax(maxThZ[cath[i]], notSaturated[i] * z[i]);
768 }
769 double var[2] = {cathMax[0] / maxThZ[0], cathMax[1] / maxThZ[1]};
770 for (int i = 0; i < N; i++) {
771 z[i] = z[i] * var[cath[i]];
772 }
773 }
774
775 // ??? why abs value for penalties
776 double wPenal = abs(1.0 - vectorSum(w, K - 1) + lastW);
777 // Not Used: zPenal
778 // double zPenal = abs( 1.0 - vectorSum( z, N ) );
779 //
780 // Charge on cathodes penalisation
781 double zCath0 = 0.0, zCath1 = 0.0;
782 for (int i = 0; i < N; i++) {
783 if (cath[i] == 0) {
784 zCath0 += (z[i] * notSaturated[i]);
785 } else {
786 zCath1 += (z[i] * notSaturated[i]);
787 }
788 }
789 if (verbose > 1) {
790 printf(" non saturated sum zCath0/1 %f %f\n", zCath0, zCath1);
791 }
792 double cathPenal =
793 fabs(zCathTotalCharge[0] - zCath0) + fabs(zCathTotalCharge[1] - zCath1);
794 // ??? vectorAdd( zObs, -1.0, residual );
795 // TODO Optimize (elementwise not a good solution)
796 for (i = 0; i < N; i++) {
797 // gsl_vector_set(residuals, i, (zObs[i] - z[i]) * (1.0 + cathPenal) +
798 // wPenal);
799 double mask;
800 if ((notSaturated[i] == 0) && (z[i] < zObs[i])) {
801 mask = 1;
802 } else {
803 mask = notSaturated[i];
804 }
805 gsl_vector_set(residuals, i, mask * (zObs[i] - z[i]) + 0. * wPenal);
806 }
807 if (verbose > 1) {
808 printf(" observed sumCath0=%15.8f, sumCath1=%15.8f,\n",
809 zCathTotalCharge[0], zCathTotalCharge[1]);
810 printf(" fitted sumCath0=%15.8f, sumCath1=%15.8f,\n", zCath0, zCath1);
811 printf(" cathPenal=%5.4g wPenal=%5.4g \n", 1.0 + cathPenal, wPenal);
812 printf(" residual\n");
813 printf(" %15s %15s %15s %15s %15s %15s\n", "zObs", "z", "cathWeight",
814 "norm. factor", "notSaturated", "residual");
815 for (i = 0; i < N; i++) {
816 printf(" %15.8f %15.8f %15.8f %15.8f %d %15.8f\n", zObs[i],
817 z[i], cathWeights[i], sumNormalizedZ[cath[i]] * cathWeights[i],
818 notSaturated[i], gsl_vector_get(residuals, i));
819 }
820 printf("\n");
821 }
822 return GSL_SUCCESS;
823}
824
825void printState(int iter, gsl_multifit_fdfsolver* s, int K, int N)
826{
827 printf(" Fitting iter=%3d |f(x)| =%g\n", iter, gsl_blas_dnrm2(s->f));
828 printf(" mu (x,y):");
829 int k = 0;
830 for (; k < 2 * K; k++) {
831 printf(" % 7.3f", gsl_vector_get(s->x, k));
832 }
833 printf("\n");
834 double sumW = 0;
835 printf(" w:");
836 for (; k < 3 * K - 1; k++) {
837 double w = gsl_vector_get(s->x, k);
838 sumW += w;
839 printf(" %7.3f", gsl_vector_get(s->x, k));
840 }
841 // Last w : 1.0 - sumW
842 printf(" %7.3f", 1.0 - sumW);
843
844 printf("\n");
845 k = 0;
846 printf(" dx:");
847 for (; k < 2 * K; k++) {
848 printf(" % 7.3f", gsl_vector_get(s->dx, k));
849 }
850 printf("\n");
851 printf(" Jacobian");
852 double sum = 0.0;
853 for (int k=0; k < K; k++) {
854 printf(" k:");
855 for (int i=0; i < N; i++) {
856 printf(" % 7.3f", gsl_matrix_get (s->J, i, k) );
857 }
858 printf("\n");
859 }
860 printf("\n");
861}
862*/
863
864// Notes :
865// - the intitialization of Mathieson module must be done before
866// (initMathieson)
867// zCathTotalCharge = sum excludind saturated pads
868namespace o2
869{
870namespace mch
871{
872void printState(int iter, gsl_multifit_fdfsolver* s, int axe, int K, int N)
873{
874 printf(" Fitting iter=%3d |f(x)|=%g\n", iter, gsl_blas_dnrm2(s->f));
875 if (axe == 0) {
876 printf(" mu (x):");
877 } else if (axe == 1) {
878 printf(" mu (y):");
879 } else {
880 printf(" mu (x,y):");
881 }
882 int k = 0;
883 if (axe == -1) {
884 for (; k < 2 * K; k++) {
885 printf(" % 7.3f", gsl_vector_get(s->x, k));
886 }
887 printf("\n");
888 } else {
889 for (; k < 1 * K; k++) {
890 printf(" % 7.3f", gsl_vector_get(s->x, k));
891 }
892 printf("\n");
893 }
894 double sumW = 0;
895 printf(" w:");
896 int nDimensions = (axe == -1) ? 3 : 2;
897 for (; k < nDimensions * K - 1; k++) {
898 double w = gsl_vector_get(s->x, k);
899 sumW += w;
900 printf(" %7.3f", gsl_vector_get(s->x, k));
901 }
902 // Last w : 1.0 - sumW
903 printf(" %7.3f", 1.0 - sumW);
904
905 printf("\n");
906 k = 0;
907 double dxMax = -1.0;
908 printf(" dxyw:");
909 for (; k < (nDimensions - 1) * K; k++) {
910 double dx_k = gsl_vector_get(s->dx, k);
911 printf(" %7.3f", dx_k);
912 dxMax = (dxMax < dx_k) ? dx_k : dxMax;
913 }
914 printf("\n");
915 printf(" max(dxyw) = %7.3f", dxMax);
916 printf(" Jacobian\n");
917 double sum = 0.0;
918 for (int k = 0; k < K; k++) {
919 if (nDimensions == 3) {
920 printf(" k=%2d mux:", k);
921 for (int i = 0; i < N; i++) {
922#if GSL_MAJOR_VERSION < 2
923 printf(" % 7.3f", gsl_matrix_get(s->J, i, k));
924#endif
925 }
926 printf("\n");
927 }
928 printf(" k=%2d mux/y:", k);
929 for (int i = 0; i < N; i++) {
930#if GSL_MAJOR_VERSION < 2
931 printf(" % 7.3f", gsl_matrix_get(s->J, i, k + (nDimensions - 2) * K));
932#endif
933 }
934 printf("\n");
935 if (k < K - 1) {
936 printf(" k=%2d w :", k);
937 for (int i = 0; i < N; i++) {
938#if GSL_MAJOR_VERSION < 2
939 printf(" % 7.3f", gsl_matrix_get(s->J, i, k + (nDimensions - 1) * K));
940#endif
941 }
942 }
943 printf("\n");
944 }
945 printf("\n");
946}
947
948void fitMathieson(const Pads& iPads, double* thetaInit, int kInit,
949 int dimOfParameters, int axe, int mode,
950 double* thetaFinal, double* khi2, double* pError)
951{
952 int status;
953
954 // process / mode
955 int p = mode;
956 // verbose unused ???
957 int verbose = p & 0x3;
958 p = p >> 2;
959 int doJacobian = p & 0x1;
960 p = p >> 1;
961 int computeKhi2 = p & 0x1;
962 p = p >> 1;
963 int computeStdDev = p & 0x1;
965 printf("\n> [fitMathieson] Fitting \n");
966 printf(
967 " mode: verbose, doJacobian, computeKhi2, computeStdDev %d %d %d %d\n",
968 verbose, doJacobian, computeKhi2, computeStdDev);
969 }
970 //
971 // int N = iPads.getNbrOfPads();
972 int N;
973 if (axe == -1) {
974 N = iPads.getNbrOfPads();
975 } else {
976 N = iPads.getNbrOfObsPads();
977 }
978 //
979 double* muAndWi = getMuAndW(thetaInit, kInit);
980 //
981 // Check if fitting is possible
982 double* muAndWf = getMuAndW(thetaFinal, kInit);
983 if (dimOfParameters * kInit - 1 > N) {
984 muAndWf[0] = NAN;
985 muAndWf[kInit] = NAN;
986 muAndWf[2 * kInit] = NAN;
987 return;
988 }
989
990 funcDescription_t mathiesonData;
991 double cathMax[2] = {0.0, 0.0};
992 double* cathWeights;
993
995 vectorPrintShort(" iPads.cath", iPads.getCathodes(), N);
996 vectorPrint(" iPads.q", iPads.getCharges(), N);
997 }
998
999 // if( 1 ) {
1000 // Add boundary Pads
1001 // pads = Pads::addBoundaryPads( iPads.x, iPads.y, iPads.dx, iPads.dy,
1002 // iPads.q, iPads.cath, iPads.saturate, iPads.chamberId, iPads.nPads );
1003
1004 // Function description (extra data nor parameters)
1005 mathiesonData.N = N;
1006 mathiesonData.K = kInit;
1007 double* xInf = new double[N];
1008 double* xSup = new double[N];
1009 double* yInf = new double[N];
1010 double* ySup = new double[N];
1011 vectorAddVector(iPads.getX(), -1.0, iPads.getDX(), N, xInf);
1012 vectorAddVector(iPads.getX(), +1.0, iPads.getDX(), N, xSup);
1013 vectorAddVector(iPads.getY(), -1.0, iPads.getDY(), N, yInf);
1014 vectorAddVector(iPads.getY(), +1.0, iPads.getDY(), N, ySup);
1015 mathiesonData.xInf_ptr = xInf;
1016 mathiesonData.yInf_ptr = yInf;
1017 mathiesonData.xSup_ptr = xSup;
1018 mathiesonData.ySup_ptr = ySup;
1019 mathiesonData.cath_ptr = iPads.getCathodes();
1020 mathiesonData.zObs_ptr = iPads.getCharges();
1021 Mask_t notSaturated[N];
1022 vectorCopyShort(iPads.getSaturates(), N, notSaturated);
1023 vectorNotShort(notSaturated, N, notSaturated);
1024 mathiesonData.notSaturated_ptr = notSaturated;
1025 mathiesonData.dimOfParameters = dimOfParameters;
1026 mathiesonData.axe = axe;
1027 mathiesonData.compressedPads = compressPads(xInf, xSup, yInf, ySup, N);
1028 //} else {
1029 /*
1030 // Function description (extra data nor parameters)
1031 mathiesonData.N = N;
1032 mathiesonData.K = kInit;
1033 mathiesonData.x_ptr = iPads.x;
1034 mathiesonData.y_ptr = iPads.y;
1035 mathiesonData.dx_ptr = iPads.dx;
1036 mathiesonData.dy_ptr = iPads.dy;
1037 mathiesonData.cath_ptr = iPads.cath;
1038 mathiesonData.zObs_ptr = iPads.q;
1039 Mask_t notSaturated[N];
1040 vectorCopyShort( iPads.saturate, N, notSaturated);
1041 vectorNotShort( notSaturated, N, notSaturated );
1042 mathiesonData.notSaturated_ptr = notSaturated;
1043 }
1044 */
1045 // Total Charge per cathode plane
1046 double zCathTotalCharge[2];
1047 double cathCoefNorm[2] = {0.0};
1048 Mask_t mask[N];
1049 // Cath 1
1050 vectorCopyShort(mathiesonData.cath_ptr, N, mask);
1051 // Logic And operation
1052 vectorMultVectorShort(mathiesonData.notSaturated_ptr, mask, N, mask);
1053 zCathTotalCharge[0] = vectorMaskedSum(mathiesonData.zObs_ptr, mask, N);
1054 // cath 0
1055 vectorCopyShort(mathiesonData.cath_ptr, N, mask);
1056 vectorNotShort(mask, N, mask);
1057 // Logic And operation
1058 vectorMultVectorShort(mathiesonData.notSaturated_ptr, mask, N, mask);
1059 zCathTotalCharge[1] = vectorMaskedSum(mathiesonData.zObs_ptr, mask, N);
1060
1061 // Init the weights
1062 cathWeights = new double[N];
1063 for (int i = 0; i < N; i++) {
1064 cathWeights[i] = (mathiesonData.cath_ptr[i] == 0) ? zCathTotalCharge[0]
1065 : zCathTotalCharge[1];
1066 cathMax[mathiesonData.cath_ptr[i]] = std::fmax(
1067 cathMax[mathiesonData.cath_ptr[i]],
1068 mathiesonData.notSaturated_ptr[i] * mathiesonData.zObs_ptr[i]);
1069 }
1071 vectorPrintShort("mathiesonData.cath_ptr", mathiesonData.cath_ptr, N);
1072 vectorPrintShort("mathiesonData.notSaturated_ptr",
1073 mathiesonData.notSaturated_ptr, N);
1074 vectorPrint("mathiesonData.zObs_ptr", mathiesonData.zObs_ptr, N);
1075 }
1076 mathiesonData.cathWeights_ptr = cathWeights;
1077 mathiesonData.cathMax_ptr = cathMax;
1078 mathiesonData.chamberId = iPads.getChamberId();
1079 mathiesonData.zCathTotalCharge_ptr = zCathTotalCharge;
1080 mathiesonData.cathCoefNorm_ptr = cathCoefNorm;
1081 mathiesonData.verbose = verbose;
1082 //
1083 // Define Function, jacobian
1084 gsl_multifit_function_fdf f;
1085 f.f = &f_ChargeIntegral;
1086 f.df = nullptr;
1087 // f.df = df_ChargeIntegral;
1088 f.fdf = nullptr;
1089 f.n = N;
1090 f.p = dimOfParameters * kInit - 1;
1091 f.params = &mathiesonData;
1092
1093 bool doFit = true;
1094 // K test
1095 int K = kInit;
1096 // Sort w
1097 int maxIndex[kInit];
1098 for (int k = 0; k < kInit; k++) {
1099 maxIndex[k] = k;
1100 }
1101 double* w = &muAndWi[2 * kInit];
1102 std::sort(maxIndex, &maxIndex[kInit],
1103 [=](int a, int b) { return (w[a] > w[b]); });
1104 // Remove this loop ???
1105 int iter = 0;
1106 while (doFit) {
1107 // Select the best K's
1108 // Copy kTest max
1109 double muAndWTest[dimOfParameters * K];
1110 // Mu part
1111 if (dimOfParameters == 3) {
1112 for (int k = 0; k < K; k++) {
1113 // Respecttively mux, muy, w
1114 muAndWTest[k] = muAndWi[maxIndex[k]];
1115 muAndWTest[k + K] = muAndWi[maxIndex[k] + kInit];
1116 muAndWTest[k + 2 * K] = muAndWi[maxIndex[k] + 2 * kInit];
1117 }
1118 } else {
1119 for (int k = 0; k < K; k++) {
1120 // Respecttively mux, muy, w
1121 if (axe == 0) {
1122 // x axe
1123 muAndWTest[k] = muAndWi[maxIndex[k]];
1124 } else {
1125 // y axe
1126 muAndWTest[k] = muAndWi[maxIndex[k] + kInit];
1127 }
1128 // w
1129 if (K != 1) {
1130 muAndWTest[k + K] = muAndWi[maxIndex[k] + 2 * kInit];
1131 }
1132 }
1133 }
1134
1136 if (dimOfParameters == 3) {
1137 vectorPrint(" Selected w", &muAndWTest[2 * K], K);
1138 vectorPrint(" Selected mux", &muAndWTest[0], K);
1139 vectorPrint(" Selected muy", &muAndWTest[K], K);
1140 } else {
1141 printf(" Selected dimOfParameters=2, axe=%d", axe);
1142 vectorPrint(" Selected w ", &muAndWTest[K], K);
1143 vectorPrint(" Selected muxy", &muAndWTest[0], K);
1144 }
1145 }
1146 mathiesonData.K = K;
1147 f.p = dimOfParameters * K - 1;
1148 // Set initial parameters
1149 // Inv ??? gsl_vector_view params0 = gsl_vector_view_array(muAndWi, 3 * K -
1150 // 1);
1151 gsl_vector_view params0 = gsl_vector_view_array(muAndWTest, dimOfParameters * K - 1);
1152
1153 // Fitting method
1154 gsl_multifit_fdfsolver* s = gsl_multifit_fdfsolver_alloc(
1155 gsl_multifit_fdfsolver_lmsder, N, dimOfParameters * K - 1);
1156 // associate the fitting mode, the function, and the starting parameters
1157 gsl_multifit_fdfsolver_set(s, &f, &params0.vector);
1158
1160 o2::mch::printState(-1, s, axe, K, N);
1161 }
1162 // double initialResidual = gsl_blas_dnrm2(s->f);
1163 double initialResidual = 0.0;
1164 // Fitting iteration
1165 status = GSL_CONTINUE;
1166 double residual = DBL_MAX;
1167 double prevResidual = DBL_MAX;
1168 double prevTheta[dimOfParameters * K - 1];
1169 // ??? for (int iter = 0; (status == GSL_CONTINUE) && (iter < 500); iter++)
1170 // {
1171 for (; (status == GSL_CONTINUE) && (iter < 50); iter++) {
1172 // TODO: to speed if possible
1173 for (int k = 0; k < (dimOfParameters * K - 1); k++) {
1174 prevTheta[k] = gsl_vector_get(s->x, k);
1175 }
1176 // printf(" Debug Fitting iter=%3d |f(x)|=%g\n", iter,
1177 // gsl_blas_dnrm2(s->f));
1178 status = gsl_multifit_fdfsolver_iterate(s);
1180 printf(" Solver status = %s\n", gsl_strerror(status));
1181 }
1183 o2::mch::printState(iter, s, axe, K, N);
1184 }
1185 /* ???? Inv
1186 if (status) {
1187 printf(" ???? End fitting \n");
1188 break;
1189 };
1190 */
1191 // GG TODO ???: adjust error in fct of charge
1192 status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4);
1194 printf(" Status multifit_test_delta = %d %s\n", status,
1195 gsl_strerror(status));
1196 }
1197 // Residu
1198 prevResidual = residual;
1199 residual = gsl_blas_dnrm2(s->f);
1200 // vectorPrint(" prevtheta", prevTheta, 3*K-1);
1201 // vectorPrint(" theta", s->dx->data, 3*K-1);
1202 // printf(" prevResidual, residual %f %f\n", prevResidual, residual );
1203 //
1204 // max dx/dy (dw not included)
1205 double tmp[(dimOfParameters - 1) * K];
1206 vectorAbs(s->dx->data, (dimOfParameters - 1) * K, tmp);
1207 double maxDxy = vectorMax(tmp, (dimOfParameters - 1) * K);
1208 bool converged = (fabs(prevResidual - residual) / residual < 1.0e-2) || (maxDxy < clusterConfig.minFittingXYStep);
1209 if (converged) {
1210 // Stop iteration
1211 // Take the previous value of theta
1213 printf(" Stop iteration iteration=%d (dResidu/residu~0), prevResidual=%f residual=%f\n",
1214 iter, prevResidual, residual);
1215 printf(" End max dxy=%f\n", vectorMax(s->dx->data, (dimOfParameters - 1) * K));
1216 if (K > 1) {
1217 printf(" End max dw=%f\n", vectorMax(&s->dx->data[(dimOfParameters - 1) * K], K - 1));
1218 }
1219 }
1220 for (int k = 0; k < (dimOfParameters * K - 1); k++) {
1221 gsl_vector_set(s->x, k, prevTheta[k]);
1222 }
1223 status = GSL_SUCCESS;
1224 }
1225 }
1226 double finalResidual = gsl_blas_dnrm2(s->f);
1227 bool keepInitialTheta =
1228 fabs(finalResidual - initialResidual) / initialResidual < 1.0e-1;
1229
1230 // Khi2
1231 if (computeKhi2 && (khi2 != nullptr)) {
1232 // Khi2
1233 double chi = gsl_blas_dnrm2(s->f);
1234 double dof = N - (dimOfParameters * K - 1);
1235 double c = fmax(1.0, chi / sqrt(dof));
1237 printf(" K=%d, chi=%f, chisq/dof = %g\n", K, chi * chi,
1238 chi * chi / dof);
1239 }
1240 khi2[0] = chi * chi / dof;
1241 }
1242
1243 // ???? if (keepInitialTheta) {
1244 if (0) {
1245 // Keep the result of EM (GSL bug when no improvemebt)
1246 copyTheta(thetaInit, kInit, thetaFinal, kInit, kInit);
1247 } else {
1248 // Fitted parameters
1249 /* Invalid ???
1250 for (int k = 0; k < (3 * K - 1); k++) {
1251 muAndWf[k] = gsl_vector_get(s->x, k);
1252 }
1253 */
1254
1255 // Mu part
1256 for (int k = 0; k < K; k++) {
1257 if (axe == 0) {
1258 // x
1259 muAndWf[k] = gsl_vector_get(s->x, k);
1260 // y
1261 // muAndWf[k+kInit] = mathiesonData.y_ptr[0];
1262 muAndWf[k + kInit] = iPads.getY()[0];
1263 } else if (axe == 1) {
1264 // x
1265 // muAndWf[k] = mathiesonData.x_ptr[0];
1266 muAndWf[k] = iPads.getX()[0];
1267 // y
1268 muAndWf[k + kInit] = gsl_vector_get(s->x, k);
1269 } else if (axe == -1) {
1270 // x
1271 muAndWf[k] = gsl_vector_get(s->x, k);
1272 // y
1273 muAndWf[k + kInit] = gsl_vector_get(s->x, k + K);
1274 }
1275 }
1276 // w part
1277 double sumW = 0;
1278 for (int k = 0; k < K - 1; k++) {
1279 double w = gsl_vector_get(s->x, k + (dimOfParameters - 1) * K);
1280 sumW += w;
1281 muAndWf[k + 2 * kInit] = w;
1282 }
1283 // Last w : 1.0 - sumW
1284 muAndWf[3 * kInit - 1] = 1.0 - sumW;
1285 // Parameter error
1286 /* Pb Mac compilation
1287 if (computeStdDev && (pError != nullptr)) { //
1288 // Covariance matrix an error
1289 gsl_matrix* covar = gsl_matrix_alloc(3 * K - 1, 3 * K - 1);
1290 gsl_multifit_covar(s->J, 0.0, covar);
1291 for (int k = 0; k < (3 * K - 1); k++) {
1292 pError[k] = sqrt(gsl_matrix_get(covar, k, k));
1293 }
1294 gsl_matrix_free(covar);
1295 }
1296 */
1297 }
1299 printf(" status parameter error = %s\n", gsl_strerror(status));
1300 }
1301 gsl_multifit_fdfsolver_free(s);
1302 K = K - 1;
1303 // doFit = (K < 3) && (K > 0);
1304 doFit = false;
1305 } // while(doFit)
1306 // Release memory
1307 delete[] cathWeights;
1308 delete[] xInf;
1309 delete[] xSup;
1310 delete[] yInf;
1311 delete[] ySup;
1312 deleteCompressedPads(mathiesonData.compressedPads);
1313 delete mathiesonData.compressedPads;
1314
1315 // printf("End fitting: iteration=%d nPads=%d \n", iter, N);
1316 return;
1317}
1318
1319} // namespace mch
1320} // namespace o2
1321
1322void fitMathieson(const double* x, const double* y, const double* dx, const double* dy, const double* q,
1323 const o2::mch::Mask_t* cath, const o2::mch::Mask_t* sat, int chId, int nPads,
1324 double* thetaInit, int kInit,
1325 double* thetaFinal, double* khi2, double* pError)
1326{
1327 //
1328 Pads pads = o2::mch::Pads(x, y, dx, dy, q, cath, sat, chId, nPads);
1329 // Default
1330 int mode = 0;
1331 int dimOfParameters = 3;
1332 int axe = -1;
1333 o2::mch::fitMathieson(pads, thetaInit, kInit,
1334 dimOfParameters, axe, mode,
1335 thetaFinal, khi2, pError);
1336}
int32_t i
float float float & zMax
uint32_t c
Definition RawData.h:2
const double * getX() const
Definition PadsPEM.h:91
const Mask_t * getCathodes() const
Definition PadsPEM.h:101
int getChamberId() const
Definition PadsPEM.h:106
static int getNbrOfPads(const Pads *pads)
Definition PadsPEM.h:63
const double * getDY() const
Definition PadsPEM.h:94
const double * getCharges() const
Definition PadsPEM.h:99
const double * getY() const
Definition PadsPEM.h:92
int getNbrOfObsPads() const
Definition PadsPEM.h:90
const Mask_t * getSaturates() const
Definition PadsPEM.h:100
const double * getDX() const
Definition PadsPEM.h:93
float sum(float s, o2::dcs::DataPointValue v)
Definition dcs-ccdb.cxx:39
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum mode
Definition glcorearb.h:266
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum const GLfloat * params
Definition glcorearb.h:272
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
GLint GLuint mask
Definition glcorearb.h:291
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
double chargeNormalization(const Mask_t *cath, const Mask_t *notSaturated, const double *cathMaxObs, int N, double *z, double *coefNorm)
int f_ChargeIntegral(const gsl_vector *gslParams, void *dataFit, gsl_vector *residuals)
void vectorPrintShort(const char *str, const short *x, int K)
Definition mathUtil.cxx:43
CompressedPads_t * compressPads(const double *xInf, const double *xSup, const double *yInf, const double *ySup, int N)
void compute1DPadIntegrals(const double *xyInf, const double *xySup, int N, double xy0, int axe, int chamberId, double *integrals)
void copyTheta(const double *theta0, int K0, double *theta, int K1, int K)
double * getMuAndW(double *theta, int K)
void vectorPrint(const char *str, const double *x, int K)
Definition mathUtil.cxx:20
void printState(int iter, gsl_multifit_fdfsolver *s, int axe, int K, int N)
void computeCompressed2DPadIntegrals(CompressedPads_t *compressedPads, double xShift, double yShift, int N, int chamberId, double Integrals[])
void deleteCompressedPads(CompressedPads_t *compressedPads)
ClusterConfig clusterConfig
void fitMathieson(const Pads &iPads, double *thetaInit, int kInit, int dimOfParameters, int axe, int mode, double *thetaFinal, double *khi2, double *pError)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
@ info
Describes main steps and high level behaviors.
@ detail
Describes in detail.
double * cathWeights_ptr
double * cathCoefNorm_ptr
const double * xSup_ptr
double * zCathTotalCharge_ptr
const double * zObs_ptr
const double * yInf_ptr
Mask_t * notSaturated_ptr
CompressedPads_t * compressedPads
const Mask_t * cath_ptr
const double * ySup_ptr
double * cathMax_ptr
const double * xInf_ptr