File indexing completed on 2023-03-17 10:43:55
0001
0002
0003
0004
0005
0006
0007 #include "Calibration/Tools/interface/HouseholderDecomposition.h"
0008 #include <cfloat>
0009 #include <cmath>
0010 #include <cstdlib>
0011
0012 HouseholderDecomposition::HouseholderDecomposition(int squareMode_, int mineta_, int maxeta_, int minphi_, int maxphi_)
0013 : squareMode(squareMode_), countEvents(0), mineta(mineta_), maxeta(maxeta_), minphi(minphi_), maxphi(maxphi_) {
0014 Neta = maxeta - mineta + 1;
0015 if (mineta * maxeta < 0)
0016 Neta--;
0017 Nphi = maxphi - minphi + 1;
0018 if (Nphi < 0)
0019 Nphi += 360;
0020
0021 Nchannels = Neta * Nphi;
0022
0023 Nxtals = squareMode * squareMode;
0024
0025 sigmaReplacement = 0.00001;
0026 }
0027
0028 HouseholderDecomposition::~HouseholderDecomposition() {}
0029
0030 std::vector<float> HouseholderDecomposition::runRegional(const std::vector<std::vector<float> >& eventMatrix,
0031 const std::vector<int>& VmaxCeta,
0032 const std::vector<int>& VmaxCphi,
0033 const std::vector<float>& energyVector,
0034 const int& nIter,
0035 const int& regLength) {
0036
0037 makeRegions(regLength);
0038
0039 Nevents = eventMatrix.size();
0040
0041 std::vector<float> totalSolution(Nchannels, 1.);
0042 std::vector<float> iterSolution(Nchannels, 1.);
0043 std::vector<std::vector<float> > myEventMatrix(eventMatrix);
0044
0045
0046 for (int iter = 1; iter <= nIter; iter++) {
0047
0048 for (unsigned int ireg = 0; ireg < regMinEta.size(); ireg++) {
0049 std::vector<float> regIterSolution, regEnergyVector;
0050 std::vector<int> regVmaxCeta, regVmaxCphi;
0051 std::vector<std::vector<float> > regEventMatrix;
0052
0053
0054 HouseholderDecomposition regionalHH(
0055 squareMode, regMinEta[ireg], regMaxEta[ireg], regMinPhi[ireg], regMaxPhi[ireg]);
0056
0057
0058 for (unsigned int ia = 0; ia < VmaxCeta.size(); ia++) {
0059 if ((VmaxCeta[ia] >= regMinEta[ireg]) && (VmaxCeta[ia] <= regMaxEta[ireg]) &&
0060 (VmaxCphi[ia] >= regMinPhi[ireg]) && (VmaxCphi[ia] <= regMaxPhi[ireg])) {
0061
0062 regVmaxCeta.push_back(VmaxCeta[ia]);
0063 regVmaxCphi.push_back(VmaxCphi[ia]);
0064
0065 std::vector<float> regEvent = myEventMatrix[ia];
0066 float regEnergy = energyVector[ia];
0067 for (int i2 = 0; i2 < Nxtals; i2++) {
0068 int iFullReg = regionalHH.indexSqr2Reg(i2, VmaxCeta[ia], VmaxCphi[ia]);
0069 if (iFullReg < 0)
0070 {
0071 regEnergy -= regEvent[i2];
0072 regEvent[i2] = 0.;
0073 }
0074 }
0075 regEventMatrix.push_back(regEvent);
0076 regEnergyVector.push_back(regEnergy);
0077 }
0078 }
0079
0080
0081
0082
0083 regIterSolution = regionalHH.iterate(regEventMatrix, regVmaxCeta, regVmaxCphi, regEnergyVector);
0084
0085
0086
0087
0088 for (unsigned int i1 = 0; i1 < regIterSolution.size(); i1++) {
0089 int regFrame = regLength / 2;
0090 int currRegPhiRange = regMaxPhi[ireg] - regMinPhi[ireg] + 1;
0091 int currRegEta = i1 / currRegPhiRange + regMinEta[ireg];
0092 int currRegPhi = i1 % currRegPhiRange + regMinPhi[ireg];
0093 int newindex = -100;
0094
0095 if ((currRegEta >= (regMinEta[ireg] + regFrame * (!(regMinEta[ireg] == mineta)))) &&
0096 (currRegEta <= (regMaxEta[ireg] - regFrame * (!(regMaxEta[ireg] == maxeta)))) &&
0097 (currRegPhi >= (regMinPhi[ireg] + regFrame * (!(regMinPhi[ireg] == minphi)))) &&
0098 (currRegPhi <= (regMaxPhi[ireg] - regFrame * (!(regMaxPhi[ireg] == maxphi))))) {
0099 newindex = (currRegEta - mineta) * Nphi + currRegPhi - minphi;
0100 iterSolution[newindex] = regIterSolution[i1];
0101 }
0102 }
0103 }
0104
0105 if (iterSolution.empty())
0106 return iterSolution;
0107
0108
0109 for (int ievent = 0; ievent < Nevents; ievent++) {
0110 myEventMatrix[ievent] = recalibrateEvent(myEventMatrix[ievent], VmaxCeta[ievent], VmaxCphi[ievent], iterSolution);
0111 }
0112
0113
0114 for (int i = 0; i < Nchannels; i++) {
0115 totalSolution[i] *= iterSolution[i];
0116 }
0117
0118 }
0119
0120 return totalSolution;
0121 }
0122
0123 std::vector<float> HouseholderDecomposition::iterate(const std::vector<std::vector<float> >& eventMatrix,
0124 const std::vector<int>& VmaxCeta,
0125 const std::vector<int>& VmaxCphi,
0126 const std::vector<float>& energyVector,
0127 const int& nIter,
0128 const bool& normalizeFlag) {
0129 Nevents = eventMatrix.size();
0130
0131 std::vector<float> totalSolution(Nchannels, 1.);
0132 std::vector<float> iterSolution;
0133 std::vector<std::vector<float> > myEventMatrix(eventMatrix);
0134 std::vector<float> myEnergyVector(energyVector);
0135
0136 int i, j;
0137
0138
0139 for (int iter = 1; iter <= nIter; iter++) {
0140
0141 float sumOverEnergy;
0142 if (normalizeFlag) {
0143 float scale = 0.;
0144
0145 for (i = 0; i < Nevents; i++) {
0146 sumOverEnergy = 0.;
0147 for (j = 0; j < Nxtals; j++) {
0148 sumOverEnergy += myEventMatrix[i][j];
0149 }
0150 sumOverEnergy /= myEnergyVector[i];
0151 scale += sumOverEnergy;
0152 }
0153 scale /= Nevents;
0154
0155 for (i = 0; i < Nevents; i++) {
0156 myEnergyVector[i] *= scale;
0157 }
0158 }
0159
0160
0161 iterSolution = iterate(myEventMatrix, VmaxCeta, VmaxCphi, myEnergyVector);
0162
0163 if (iterSolution.empty())
0164 return iterSolution;
0165
0166
0167 for (int ievent = 0; ievent < Nevents; ievent++) {
0168 myEventMatrix[ievent] = recalibrateEvent(myEventMatrix[ievent], VmaxCeta[ievent], VmaxCphi[ievent], iterSolution);
0169 }
0170
0171 for (int i = 0; i < Nchannels; i++) {
0172
0173 totalSolution[i] *= iterSolution[i];
0174 }
0175
0176 }
0177
0178 return totalSolution;
0179 }
0180
0181 std::vector<float> HouseholderDecomposition::iterate(const std::vector<std::vector<float> >& eventMatrix,
0182 const std::vector<int>& VmaxCeta,
0183 const std::vector<int>& VmaxCphi,
0184 const std::vector<float>& energyVectorOrig) {
0185 std::vector<float> solution;
0186
0187 Nevents = eventMatrix.size();
0188
0189 if (Nchannels > Nevents) {
0190 std::cout << "Householder::runIter(): more channels to calibrate than events available. " << std::endl;
0191 std::cout << " Nchannels=" << Nchannels << std::endl;
0192 std::cout << " Nevents=" << Nevents << std::endl;
0193 std::cout << " ****************** ERROR *********************" << std::endl;
0194 return solution;
0195 }
0196
0197
0198 eventMatrixOrig = unzipMatrix(eventMatrix, VmaxCeta, VmaxCphi);
0199
0200 if (eventMatrixOrig.size() != energyVectorOrig.size()) {
0201 std::cout << "Householder::runIter(): matrix dimensions non-conformant. " << std::endl;
0202 std::cout << " energyVectorOrig.size()=" << energyVectorOrig.size() << std::endl;
0203 std::cout << " eventMatrixOrig.size()=" << eventMatrixOrig.size() << std::endl;
0204 std::cout << " ****************** ERROR *********************" << std::endl;
0205 return solution;
0206 }
0207
0208 int i, j;
0209 eventMatrixProc = eventMatrixOrig;
0210 energyVectorProc = energyVectorOrig;
0211 std::vector<float> e(Nchannels);
0212 alpha.assign(Nchannels, 0.);
0213 pivot.assign(Nchannels, 0);
0214
0215
0216 bool decomposeSuccess = decompose();
0217
0218 if (!decomposeSuccess) {
0219 std::cout << "Householder::runIter(): Failed: Singular condition in decomposition." << std::endl;
0220 std::cout << "***************** PROBLEM in DECOMPOSITION *************************" << std::endl;
0221 return solution;
0222 }
0223
0224
0225 float mydbleps = 2.22045e-16;
0226 float etasqr = mydbleps * mydbleps;
0227
0228
0229
0230
0231 solution.assign(Nchannels, 0.);
0232 solve(solution);
0233
0234
0235 for (i = 0; i < Nevents; i++) {
0236 energyVectorProc[i] = energyVectorOrig[i];
0237 for (j = 0; j < Nchannels; j++) {
0238 energyVectorProc[i] -= eventMatrixOrig[i][j] * solution[j];
0239 }
0240 }
0241
0242
0243
0244 solve(e);
0245
0246 float normy0 = 0.;
0247 float norme1 = 0.;
0248 float norme0;
0249
0250 for (i = 0; i < Nchannels; i++) {
0251 normy0 += solution[i] * solution[i];
0252 norme1 += e[i] * e[i];
0253 }
0254
0255
0256
0257
0258
0259
0260
0261 if (norme1 > (0.0625 * normy0)) {
0262
0263 }
0264
0265
0266 for (i = 0; i < Nchannels; i++) {
0267 solution[i] += e[i];
0268 }
0269
0270
0271
0272
0273
0274 while (norme1 > (etasqr * normy0)) {
0275
0276
0277 for (i = 0; i < Nevents; i++) {
0278 energyVectorProc[i] = energyVectorOrig[i];
0279 for (j = 0; j < Nchannels; j++) {
0280 energyVectorProc[i] -= eventMatrixOrig[i][j] * solution[j];
0281 }
0282 }
0283
0284
0285 solve(e);
0286
0287 norme0 = norme1;
0288 norme1 = 0.;
0289
0290 for (i = 0; i < Nchannels; i++) {
0291 norme1 += e[i] * e[i];
0292 }
0293
0294
0295
0296 if (norme1 > (0.0625 * norme0))
0297 break;
0298
0299
0300 for (i = 0; i < Nchannels; i++) {
0301 solution[i] += e[i];
0302 }
0303 }
0304
0305
0306 eventMatrixOrig.clear();
0307 eventMatrixProc.clear();
0308 energyVectorProc.clear();
0309 alpha.clear();
0310 pivot.clear();
0311
0312 return solution;
0313 }
0314
0315 bool HouseholderDecomposition::decompose() {
0316 int i, j, jbar, k;
0317 float beta, sigma, alphak, eventMatrixkk;
0318 std::vector<float> y(Nchannels);
0319 std::vector<float> sum(Nchannels);
0320
0321
0322
0323 for (j = 0; j < Nchannels; j++) {
0324
0325 sum[j] = 0.;
0326 for (i = 0; i < Nevents; i++)
0327 sum[j] += eventMatrixProc[i][j] * eventMatrixProc[i][j];
0328
0329
0330 pivot[j] = j;
0331 }
0332
0333 for (k = 0; k < Nchannels; k++) {
0334
0335 sigma = sum[k];
0336 jbar = k;
0337
0338
0339
0340 for (j = k + 1; j < Nchannels; j++) {
0341 if (sum[j] > sigma) {
0342 sigma = sum[j];
0343 jbar = j;
0344 }
0345 }
0346
0347 if (jbar != k) {
0348
0349
0350
0351 i = pivot[k];
0352 pivot[k] = pivot[jbar];
0353 pivot[jbar] = i;
0354
0355 sum[jbar] = sum[k];
0356 sum[k] = sigma;
0357
0358 for (i = 0; i < Nevents; i++) {
0359 sigma = eventMatrixProc[i][k];
0360 eventMatrixProc[i][k] = eventMatrixProc[i][jbar];
0361 eventMatrixProc[i][jbar] = sigma;
0362 }
0363 }
0364
0365
0366 sigma = 0.;
0367 for (i = k; i < Nevents; i++) {
0368 sigma += eventMatrixProc[i][k] * eventMatrixProc[i][k];
0369 }
0370
0371
0372 if (sigma == 0.) {
0373
0374
0375
0376 sigma = sigmaReplacement;
0377
0378 }
0379
0380
0381
0382
0383
0384 eventMatrixkk = eventMatrixProc[k][k];
0385
0386 if (eventMatrixkk < 0.)
0387 alpha[k] = sqrt(sigma);
0388 else
0389 alpha[k] = sqrt(sigma) * (-1.);
0390
0391 alphak = alpha[k];
0392
0393 beta = 1 / (sigma - eventMatrixkk * alphak);
0394
0395 eventMatrixProc[k][k] = eventMatrixkk - alphak;
0396
0397 for (j = k + 1; j < Nchannels; j++) {
0398 y[j] = 0.;
0399
0400 for (i = k; i < Nevents; i++) {
0401 y[j] += eventMatrixProc[i][k] * eventMatrixProc[i][j];
0402 }
0403
0404 y[j] *= beta;
0405 }
0406
0407 for (j = k + 1; j < Nchannels; j++) {
0408 for (i = k; i < Nevents; i++) {
0409 eventMatrixProc[i][j] -= eventMatrixProc[i][k] * y[j];
0410 sum[j] -= eventMatrixProc[k][j] * eventMatrixProc[k][j];
0411 }
0412 }
0413 }
0414
0415
0416
0417 return true;
0418 }
0419
0420 void HouseholderDecomposition::solve(std::vector<float>& y) {
0421 std::vector<float> z(Nchannels, 0.);
0422
0423 float gamma;
0424 int i, j;
0425
0426
0427
0428 for (j = 0; j < Nchannels; j++) {
0429
0430 gamma = 0.;
0431 for (i = j; i < Nevents; i++) {
0432 gamma += eventMatrixProc[i][j] * energyVectorProc[i];
0433 }
0434 gamma /= (alpha[j] * eventMatrixProc[j][j]);
0435
0436 for (i = j; i < Nevents; i++) {
0437 energyVectorProc[i] += gamma * eventMatrixProc[i][j];
0438 }
0439 }
0440
0441 z[Nchannels - 1] = energyVectorProc[Nchannels - 1] / alpha[Nchannels - 1];
0442
0443 for (i = Nchannels - 2; i >= 0; i--) {
0444 z[i] = energyVectorProc[i];
0445 for (j = i + 1; j < Nchannels; j++) {
0446 z[i] -= eventMatrixProc[i][j] * z[j];
0447 }
0448 z[i] /= alpha[i];
0449 }
0450
0451 for (i = 0; i < Nchannels; i++) {
0452 y[pivot[i]] = z[i];
0453 }
0454
0455
0456 }
0457
0458 std::vector<float> HouseholderDecomposition::recalibrateEvent(const std::vector<float>& eventSquare,
0459 const int& maxCeta,
0460 const int& maxCphi,
0461 const std::vector<float>& recalibrateVector) {
0462 std::vector<float> newEventSquare(eventSquare);
0463 int iFull;
0464
0465 for (int i = 0; i < Nxtals; i++) {
0466 iFull = indexSqr2Reg(i, maxCeta, maxCphi);
0467 if (iFull >= 0)
0468 newEventSquare[i] *= recalibrateVector[iFull];
0469 }
0470 return newEventSquare;
0471 }
0472
0473 int HouseholderDecomposition::indexSqr2Reg(const int& sqrIndex, const int& maxCeta, const int& maxCphi) {
0474 int regionIndex;
0475
0476
0477 int curr_eta = maxCeta - squareMode / 2 + sqrIndex % squareMode;
0478 if (curr_eta * maxCeta <= 0) {
0479 if (maxCeta > 0)
0480 curr_eta--;
0481 else
0482 curr_eta++;
0483 }
0484
0485 int curr_phi = maxCphi - squareMode / 2 + sqrIndex / squareMode;
0486 if (curr_phi < 1)
0487 curr_phi += 360;
0488 if (curr_phi > 360)
0489 curr_phi -= 360;
0490
0491 bool negPhiDirection = (maxphi < minphi);
0492 int iFullphi;
0493
0494 regionIndex = -1;
0495
0496 if (curr_eta >= mineta && curr_eta <= maxeta)
0497 if ((!negPhiDirection && (curr_phi >= minphi && curr_phi <= maxphi)) ||
0498 (negPhiDirection && !(curr_phi >= minphi && curr_phi <= maxphi))) {
0499 iFullphi = curr_phi - minphi;
0500 if (iFullphi < 0)
0501 iFullphi += 360;
0502 regionIndex = (curr_eta - mineta) * (maxphi - minphi + 1 + 360 * negPhiDirection) + iFullphi;
0503 }
0504
0505 return regionIndex;
0506 }
0507
0508 std::vector<std::vector<float> > HouseholderDecomposition::unzipMatrix(
0509 const std::vector<std::vector<float> >& eventMatrix,
0510 const std::vector<int>& VmaxCeta,
0511 const std::vector<int>& VmaxCphi) {
0512 std::vector<std::vector<float> > fullMatrix;
0513
0514 int iFull;
0515
0516 for (int i = 0; i < Nevents; i++) {
0517 std::vector<float> foo(Nchannels, 0.);
0518 for (int k = 0; k < Nxtals; k++) {
0519 iFull = indexSqr2Reg(k, VmaxCeta[i], VmaxCphi[i]);
0520 if (iFull >= 0)
0521 foo[iFull] = eventMatrix[i][k];
0522 }
0523 fullMatrix.push_back(foo);
0524 }
0525
0526 return fullMatrix;
0527 }
0528
0529 void HouseholderDecomposition::makeRegions(const int& regLength) {
0530
0531 int regFrame = squareMode / 2;
0532
0533 int remEta = Neta % regLength;
0534 if (remEta > regLength / 2)
0535 remEta -= regLength;
0536 int numSubRegEta = Neta / regLength + (remEta < 0) * 1;
0537
0538 int addtoEta = remEta / numSubRegEta;
0539 int addtomoreEta =
0540 remEta % numSubRegEta;
0541
0542
0543 int remPhi = Nphi % regLength;
0544 if (remPhi > regLength / 2)
0545 remPhi -= regLength;
0546 int numSubRegPhi = Nphi / regLength + (remPhi < 0) * 1;
0547
0548 int addtoPhi = remPhi / numSubRegPhi;
0549 int addtomorePhi =
0550 remPhi % numSubRegPhi;
0551
0552
0553 int startIndexEta = mineta;
0554 int startIndexPhi;
0555 int endIndexEta;
0556 int endIndexPhi;
0557 for (int i = 0; i < numSubRegEta; i++) {
0558 int addedLengthEta = regLength + addtoEta + addtomoreEta / abs(addtomoreEta) * (i < abs(addtomoreEta));
0559 endIndexEta = startIndexEta + addedLengthEta - 1;
0560
0561 startIndexPhi = minphi;
0562 for (int j = 0; j < numSubRegPhi; j++) {
0563 int addedLengthPhi = regLength + addtoPhi + addtomorePhi / abs(addtomorePhi) * (j < abs(addtomorePhi));
0564 endIndexPhi = startIndexPhi + addedLengthPhi - 1;
0565
0566 regMinPhi.push_back(startIndexPhi - regFrame * (j != 0));
0567 regMaxPhi.push_back(endIndexPhi + regFrame * (j != (numSubRegPhi - 1)));
0568 regMinEta.push_back(startIndexEta - regFrame * (i != 0));
0569 regMaxEta.push_back(endIndexEta + regFrame * (i != (numSubRegEta - 1)));
0570
0571 startIndexPhi = endIndexPhi + 1;
0572 }
0573 startIndexEta = endIndexEta + 1;
0574 }
0575
0576
0577
0578
0579
0580 }