CMS 3D CMS Logo

HouseholderDecomposition.cc
Go to the documentation of this file.
1 
8 #include <cfloat>
9 #include <cmath>
10 #include <cstdlib>
11 
12 HouseholderDecomposition::HouseholderDecomposition(int squareMode_, int mineta_, int maxeta_, int minphi_, int maxphi_)
13  :squareMode(squareMode_), countEvents(0),mineta(mineta_), maxeta(maxeta_), minphi(minphi_), maxphi(maxphi_)
14 {
15  Neta = maxeta - mineta + 1;
16  if (mineta * maxeta < 0) Neta--; // there's no eta index = 0
17  Nphi = maxphi - minphi + 1;
18  if (Nphi <0) Nphi += 360;
19 
20  Nchannels = Neta * Nphi; // no. of channels, get it from edges of the region
21 
22  Nxtals = squareMode*squareMode; // no. of xtals in one event
23 
24  sigmaReplacement = 0.00001; // the sum of columns is replaced by this value in case it is zero (e.g. dead crystal)
25 
26 }
27 
29 {
30 }
31 
32 
33 std::vector<float> HouseholderDecomposition::runRegional(const std::vector<std::vector<float> >& eventMatrix, const std::vector<int>& VmaxCeta, const std::vector<int>& VmaxCphi, const std::vector<float>& energyVector, const int& nIter, const int& regLength)
34 {
35  // make regions
36  makeRegions(regLength);
37 
38  Nevents = eventMatrix.size(); // Number of events to calibrate with
39 
40  std::vector<float> totalSolution(Nchannels,1.);
41  std::vector<float> iterSolution(Nchannels,1.);
42  std::vector<std::vector<float> > myEventMatrix(eventMatrix);
43 
44  // loop over nIter
45  for (int iter=1;iter<=nIter;iter++)
46  {
47  // loop over regions
48  for (unsigned int ireg=0; ireg<regMinEta.size(); ireg++)
49  {
50  std::vector<float> regIterSolution, regEnergyVector;
51  std::vector<int> regVmaxCeta, regVmaxCphi;
52  std::vector<std::vector<float> > regEventMatrix;
53 
54  // initialize new instance with regional min,max indices
55  HouseholderDecomposition regionalHH(squareMode,regMinEta[ireg],regMaxEta[ireg],regMinPhi[ireg],regMaxPhi[ireg]);
56 
57  // copy all events in region into new eventmatrix, energyvector, VmaxCeta, VmaxCphi
58  for (unsigned int ia=0; ia<VmaxCeta.size(); ia++)
59  {
60  if ((VmaxCeta[ia] >= regMinEta[ireg]) && (VmaxCeta[ia] <= regMaxEta[ireg])
61  && (VmaxCphi[ia] >= regMinPhi[ireg]) && (VmaxCphi[ia] <= regMaxPhi[ireg]))
62  {
63  // save event, calculate new eventmatrix(truncated) and energy
64  regVmaxCeta.push_back(VmaxCeta[ia]);
65  regVmaxCphi.push_back(VmaxCphi[ia]);
66 
67  std::vector<float> regEvent = myEventMatrix[ia];
68  float regEnergy = energyVector[ia];
69  for (int i2=0; i2<Nxtals; i2++)
70  {
71  int iFullReg = regionalHH.indexSqr2Reg(i2, VmaxCeta[ia], VmaxCphi[ia]);
72  if (iFullReg <0) // crystal outside
73  {
74  regEnergy -= regEvent[i2];
75  regEvent[i2] = 0.;
76  }
77  }
78  regEventMatrix.push_back(regEvent);
79  regEnergyVector.push_back(regEnergy);
80  }
81  }
82 
83  // calibrate
84  // std::cout << "HouseholderDecomposition::runRegional - Starting calibration of region " << ireg << ": eta "
85  // << regMinEta[ireg] << " to " << regMaxEta[ireg] << ", phi " << regMinPhi[ireg] << " to " << regMaxPhi[ireg] << std::endl;
86  regIterSolution = regionalHH.iterate(regEventMatrix, regVmaxCeta, regVmaxCphi, regEnergyVector);
87  // std::cout << "HouseholderDecomposition::runRegional - calibration of region finished. " << std::endl;
88 
89  // save solution into global iterSolution
90  // don't forget to delete the ones that are on the border !
91  for (unsigned int i1=0; i1<regIterSolution.size(); i1++)
92  {
93  int regFrame = regLength/2;
94  int currRegPhiRange = regMaxPhi[ireg] - regMinPhi[ireg] + 1;
95  int currRegEta = i1 / currRegPhiRange + regMinEta[ireg];
96  int currRegPhi = i1 % currRegPhiRange + regMinPhi[ireg];
97  int newindex = -100;
98  // if crystal well inside:
99  if ( (currRegEta >= (regMinEta[ireg]+regFrame*(!(regMinEta[ireg]==mineta))) ) &&
100  (currRegEta <= (regMaxEta[ireg]-regFrame*(!(regMaxEta[ireg]==maxeta))) ) &&
101  (currRegPhi >= (regMinPhi[ireg]+regFrame*(!(regMinPhi[ireg]==minphi))) ) &&
102  (currRegPhi <= (regMaxPhi[ireg]-regFrame*(!(regMaxPhi[ireg]==maxphi))) ) )
103  {
104  newindex = (currRegEta-mineta)*Nphi + currRegPhi-minphi;
105  iterSolution[newindex] = regIterSolution[i1];
106  }
107  }
108  } // end loop over regions
109 
110  if (iterSolution.empty()) return iterSolution;
111 
112  // re-calibrate eventMatrix with solution
113  for (int ievent = 0; ievent<Nevents; ievent++)
114  {
115  myEventMatrix[ievent] = recalibrateEvent(myEventMatrix[ievent], VmaxCeta[ievent], VmaxCphi[ievent], iterSolution);
116  }
117 
118  // save solution into theCalibVector
119  for (int i=0; i<Nchannels; i++)
120  {
121  totalSolution[i] *= iterSolution[i];
122  }
123 
124  } // end loop over nIter
125 
126  return totalSolution;
127 
128 }
129 
130 
131 std::vector<float> HouseholderDecomposition::iterate(const std::vector<std::vector<float> >& eventMatrix, const std::vector<int>& VmaxCeta, const std::vector<int>& VmaxCphi, const std::vector<float>& energyVector, const int& nIter, const bool& normalizeFlag)
132 {
133  Nevents = eventMatrix.size(); // Number of events to calibrate with
134 
135  std::vector<float> totalSolution(Nchannels,1.);
136  std::vector<float> iterSolution;
137  std::vector<std::vector<float> > myEventMatrix(eventMatrix);
138  std::vector<float> myEnergyVector(energyVector);
139 
140  int i, j;
141 
142  // Iterate the correction
143  for (int iter=1;iter<=nIter;iter++)
144  {
145 
146  // if normalization flag is set, normalize energies
147  float sumOverEnergy;
148  if (normalizeFlag)
149  {
150  float scale = 0.;
151 
152  for (i=0; i<Nevents; i++)
153  {
154  sumOverEnergy = 0.;
155  for (j=0; j<Nxtals; j++) {sumOverEnergy += myEventMatrix[i][j];}
156  sumOverEnergy /= myEnergyVector[i];
157  scale += sumOverEnergy;
158  }
159  scale /= Nevents;
160 
161  for (i=0; i<Nevents; i++) {myEnergyVector[i] *= scale;}
162  } // end normalize energies
163 
164 
165 
166  // now the real work starts:
167  iterSolution = iterate(myEventMatrix,VmaxCeta,VmaxCphi,myEnergyVector);
168 
169  if (iterSolution.empty()) return iterSolution;
170 
171  // re-calibrate eventMatrix with solution
172  for (int ievent = 0; ievent<Nevents; ievent++)
173  {
174  myEventMatrix[ievent] = recalibrateEvent(myEventMatrix[ievent], VmaxCeta[ievent], VmaxCphi[ievent], iterSolution);
175  }
176 
177  for (int i=0; i<Nchannels; i++)
178  {
179  // save solution into theCalibVector
180  totalSolution[i] *= iterSolution[i];
181  }
182 
183  } // end iterate correction
184 
185  return totalSolution;
186 }
187 
188 
189 
190 std::vector<float> HouseholderDecomposition::iterate(const std::vector<std::vector<float> >& eventMatrix, const std::vector<int>& VmaxCeta, const std::vector<int>& VmaxCphi, const std::vector<float>& energyVectorOrig)
191 {
192  std::vector<float> solution;
193 
194  Nevents=eventMatrix.size(); // Number of events to calibrate with
195 
196  if (Nchannels > Nevents)
197  {
198  std::cout << "Householder::runIter(): more channels to calibrate than events available. " << std::endl;
199  std::cout << " Nchannels=" << Nchannels << std::endl;
200  std::cout << " Nevents=" << Nevents << std::endl;
201  std::cout << " ****************** ERROR *********************" << std::endl;
202  return solution; // empty vector
203  }
204 
205  // input: eventMatrixOrig - the unzipped matrix
206  eventMatrixOrig = unzipMatrix(eventMatrix,VmaxCeta,VmaxCphi);
207 
208  if (eventMatrixOrig.size() != energyVectorOrig.size())
209  {
210  std::cout << "Householder::runIter(): matrix dimensions non-conformant. " << std::endl;
211  std::cout << " energyVectorOrig.size()=" << energyVectorOrig.size() << std::endl;
212  std::cout << " eventMatrixOrig.size()=" << eventMatrixOrig.size() << std::endl;
213  std::cout << " ****************** ERROR *********************" << std::endl;
214  return solution; // empty vector
215  }
216 
217 
218  int i,j;
220  energyVectorProc = energyVectorOrig; // copy energyVectorOrig vector
221  std::vector<float> e(Nchannels);
222  alpha.assign(Nchannels,0.);
223  pivot.assign(Nchannels,0);
224 
225 
226  //--------------------
227  bool decomposeSuccess = decompose();
228 
229  if( !decomposeSuccess )
230  {
231  std::cout << "Householder::runIter(): Failed: Singular condition in decomposition."<< std::endl;
232  std::cout << "***************** PROBLEM in DECOMPOSITION *************************"<<std::endl;
233  return solution; // empty vector
234  }
235 
236  /* DBL_EPSILON: Difference between 1.0 and the minimum float greater than 1.0 */
237  float mydbleps = 2.22045e-16; //DBL_EPSILON;
238  float etasqr = mydbleps*mydbleps;
239  // std::cout << "LOOK at DBL_EPSILON :" << mydbleps <<std::endl;
240 
241 
242  //--------------------
243  // apply transformations to rhs - find solution vector
244  solution.assign(Nchannels,0.);
245  solve(solution);
246 
247 
248  // compute residual vector energyVectorProc
249  for (i=0;i<Nevents;i++)
250  {
251  energyVectorProc[i] = energyVectorOrig[i];
252  for (j=0; j<Nchannels; j++)
253  {
254  energyVectorProc[i]-=eventMatrixOrig[i][j]*solution[j];
255  }
256  }
257 
258 
259  //--------------------
260  // compute first correction vector e
261  solve(e);
262 
263  float normy0=0.;
264  float norme1=0.;
265  float norme0;
266 
267 
268 
269 
270  for (i=0;i<Nchannels;i++)
271  {
272  normy0 += solution[i] * solution[i];
273  norme1 += e[i] * e[i];
274  }
275 
276 // std::cout << "Householder::runIter(): applying first correction";
277 // std::cout << " normy0 = " << normy0;
278 // std::cout << " norme1 = " << norme1 << std::endl;
279 
280  // not attempt at obtaining the solution is made unless the norm of the first
281  // correction is significantly smaller than the norm of the initial solution
282  if (norme1>(0.0625*normy0))
283  {
284  // std::cout << "Householder::runIter(): first correction is too large. Failed." << std::endl;
285  }
286 
287  // improve the solution
288  for (i=0; i<Nchannels; i++)
289  {
290  solution[i]+=e[i];
291  }
292 
293  // std::cout << "Householder::runIter(): improving solution...." << std::endl;
294 
295  //--------------------
296  // only continue iteration if the correction was significant
297  while (norme1>(etasqr*normy0))
298  {
299  // std::cout << "Householder::runIter(): norme1 = " << norme1 << std::endl;
300 
301  for (i=0; i<Nevents; i++)
302  {
303  energyVectorProc[i] = energyVectorOrig[i];
304  for (j=0; j<Nchannels; j++)
305  {
306  energyVectorProc[i] -= eventMatrixOrig[i][j] * solution[j];
307  }
308  }
309 
310  // compute next correction vector
311  solve(e);
312 
313  norme0 = norme1;
314  norme1 = 0.;
315 
316  for (i=0;i<Nchannels;i++)
317  {
318  norme1+=e[i]*e[i];
319  }
320 
321  // terminate iteration if the norm of the new correction failed to decrease
322  // significantly compared to the norm of the previous correction
323  if (norme1>(0.0625*norme0)) break;
324 
325  // apply correction vector
326  for (i=0;i<Nchannels;i++)
327  {
328  solution[i]+=e[i];
329  }
330  }
331 
332  //clean up
333  eventMatrixOrig.clear();
334  eventMatrixProc.clear();
335  energyVectorProc.clear();
336  alpha.clear();
337  pivot.clear();
338 
339 
340  return solution;
341 }
342 
343 
345 {
346  int i,j,jbar,k;
347  float beta,sigma,alphak,eventMatrixkk;
348  std::vector<float> y(Nchannels);
349  std::vector<float> sum(Nchannels);
350 
351  // std::cout << "Householder::decompose() started" << std::endl;
352 
353  for (j=0;j<Nchannels;j++)
354  {
355  // jth column sum: squared sum for each crystal
356  sum[j]=0.;
357  for (i=0;i<Nevents;i++)
358  sum[j]+=eventMatrixProc[i][j]*eventMatrixProc[i][j];
359 
360  // bookkeeping vector
361  pivot[j] = j;
362  }
363 
364  for (k=0;k<Nchannels;k++)
365  {
366  // kth Householder transformation
367  sigma = sum[k];
368  jbar = k;
369 
370  // go through all following columns
371  // find the largest sumSquared in the following columns
372  for (j=k+1;j<Nchannels;j++)
373  {
374  if (sum[j] > sigma)
375  {
376  sigma = sum[j];
377  jbar=j;
378  }
379  }
380 
381  if (jbar != k)
382  {
383  // column interchange:
384  // interchange within: bookkeeping vector, squaredSum, eventMatrixProc
385 
386  i = pivot[k];
387  pivot[k]=pivot[jbar];
388  pivot[jbar]=i;
389 
390  sum[jbar]=sum[k];
391  sum[k]=sigma;
392 
393  for (i=0;i<Nevents;i++)
394  {
395  sigma=eventMatrixProc[i][k];
397  eventMatrixProc[i][jbar]=sigma;
398  }
399  } // end column interchange
400 
401  // now store in sigma the squared sum of the readoutEnergies for this column(crystal)
402  sigma=0.;
403  for (i=k;i<Nevents;i++)
404  {
405  sigma+=eventMatrixProc[i][k]*eventMatrixProc[i][k];
406  }
407 
408  // found a zero-column, bail out
409  if (sigma == 0.)
410  {
411 // std::cout << "Householder::decompose() failed" << std::endl;
412 // return false;
413  // rof 14.12.2006: workaround to avoid failure of algorithm because of dead crystals:
414  sigma = sigmaReplacement;
415  // std::cout << "Householder::decompose - found zero column " << jbar << ", replacing sum of column elements by " << sigma << std::endl;
416  }
417 
418 
419  // the following paragraph acts only on the diagonal element:
420  // if element=0, then calculate alpha & beta
421 
422  // take the diagonal element
423  eventMatrixkk = eventMatrixProc[k][k];
424 
425  if (eventMatrixkk < 0.)
426  alpha[k] = sqrt(sigma);
427  else
428  alpha[k] = sqrt(sigma) * (-1.);
429 
430  alphak = alpha[k];
431 
432  beta = 1 / (sigma - eventMatrixkk * alphak);
433  // replace it
434  eventMatrixProc[k][k] = eventMatrixkk - alphak;
435 
436  for (j=k+1; j<Nchannels; j++)
437  {
438  y[j] = 0.;
439 
440  for (i=k; i<Nevents; i++)
441  {
442  y[j] += eventMatrixProc[i][k] * eventMatrixProc[i][j];
443  }
444 
445  y[j] *= beta;
446  }
447 
448  for (j=k+1; j<Nchannels; j++)
449  {
450  for (i=k; i<Nevents; i++)
451  {
452  eventMatrixProc[i][j] -= eventMatrixProc[i][k] * y[j];
453  sum[j] -= eventMatrixProc[k][j] * eventMatrixProc[k][j];
454  }
455  }
456  } // end of kth householder transformation
457 
458  // std::cout << "Householder::decompose() finished" << std::endl;
459 
460  return true;
461 }
462 
463 
464 void HouseholderDecomposition::solve(std::vector<float> &y)
465 {
466  std::vector<float> z(Nchannels,0.);
467 
468  float gamma;
469  int i,j;
470 
471  // std::cout << "Householder::solve() begin" << std::endl;
472 
473  for (j=0; j<Nchannels; j++)
474  {
475  // apply jth transformation to the right hand side
476  gamma = 0.;
477  for (i=j; i<Nevents; i++)
478  {
479  gamma += eventMatrixProc[i][j] * energyVectorProc[i];
480  }
481  gamma /= (alpha[j] * eventMatrixProc[j][j]);
482 
483  for (i=j; i<Nevents; i++)
484  {
485  energyVectorProc[i] += gamma * eventMatrixProc[i][j];
486  }
487  }
488 
489  z[Nchannels-1] = energyVectorProc[Nchannels-1] / alpha[Nchannels-1];
490 
491  for (i=Nchannels-2; i>=0; i--)
492  {
493  z[i] = energyVectorProc[i];
494  for (j=i+1; j<Nchannels; j++)
495  {
496  z[i] -= eventMatrixProc[i][j]*z[j];
497  }
498  z[i] /= alpha[i];
499  }
500 
501  for (i=0; i<Nchannels; i++)
502  {
503  y[pivot[i]] = z[i];
504  }
505 
506  // std::cout << "Householder::solve() finished." << std::endl;
507 
508 }
509 
510 
511 std::vector<float> HouseholderDecomposition::recalibrateEvent(const std::vector<float>& eventSquare, const int& maxCeta, const int& maxCphi, const std::vector<float>& recalibrateVector)
512 {
513  std::vector<float> newEventSquare(eventSquare);
514  int iFull;
515 
516  for (int i=0; i<Nxtals; i++)
517  {
518  iFull = indexSqr2Reg(i, maxCeta, maxCphi);
519  if (iFull >=0)
520  newEventSquare[i] *= recalibrateVector[iFull];
521  }
522  return newEventSquare;
523 }
524 
525 
526 int HouseholderDecomposition::indexSqr2Reg(const int& sqrIndex, const int& maxCeta, const int& maxCphi)
527 {
528  int regionIndex;
529 
530  // get the current eta, phi indices
531  int curr_eta = maxCeta - squareMode/2 + sqrIndex%squareMode;
532  if (curr_eta * maxCeta <= 0) {if (maxCeta > 0) curr_eta--; else curr_eta++; } // JUMP over 0
533 
534  int curr_phi = maxCphi - squareMode/2 + sqrIndex/squareMode;
535  if (curr_phi < 1) curr_phi += 360;
536  if (curr_phi > 360) curr_phi -= 360;
537 
538  bool negPhiDirection = (maxphi < minphi);
539  int iFullphi;
540 
541  regionIndex = -1;
542 
543  if (curr_eta >= mineta && curr_eta <= maxeta)
544  if ( (!negPhiDirection && (curr_phi >= minphi && curr_phi <= maxphi)) ||
545  (negPhiDirection && !(curr_phi >= minphi && curr_phi <= maxphi)) )
546  {
547  iFullphi = curr_phi - minphi;
548  if (iFullphi < 0) iFullphi += 360;
549  regionIndex = (curr_eta - mineta) * (maxphi - minphi + 1 + 360*negPhiDirection) + iFullphi;
550  }
551 
552  return regionIndex;
553 }
554 
555 std::vector<std::vector<float> > HouseholderDecomposition::unzipMatrix(const std::vector< std::vector<float> >& eventMatrix, const std::vector<int>& VmaxCeta, const std::vector<int>& VmaxCphi)
556 {
557  std::vector< std::vector<float> > fullMatrix;
558 
559  int iFull;
560 
561  for (int i=0; i<Nevents; i++)
562  {
563  std::vector<float> foo(Nchannels,0.);
564  for (int k=0; k<Nxtals; k++)
565  {
566  iFull = indexSqr2Reg(k, VmaxCeta[i], VmaxCphi[i]);
567  if (iFull >=0)
568  foo[iFull] = eventMatrix[i][k];
569  }
570  fullMatrix.push_back(foo);
571  }
572 
573  return fullMatrix;
574 }
575 
576 void HouseholderDecomposition::makeRegions(const int& regLength)
577 {
578  // int regFrame = regLength/2;
579  int regFrame = squareMode/2;
580  // first eta:
581  int remEta = Neta % regLength;
582  if (remEta > regLength/2) remEta -= regLength;
583  int numSubRegEta = Neta / regLength + (remEta < 0)*1;
584 
585  int addtoEta = remEta / numSubRegEta;
586  int addtomoreEta = remEta % numSubRegEta; // add "addtomore" number of times (addto+1), remaining times add just (addto)
587 
588  // then phi:
589  int remPhi = Nphi % regLength;
590  if (remPhi > regLength/2) remPhi -= regLength;
591  int numSubRegPhi = Nphi / regLength + (remPhi < 0)*1;
592 
593  int addtoPhi = remPhi / numSubRegPhi;
594  int addtomorePhi = remPhi % numSubRegPhi; // add "addtomore" number of times (addto+-1), remaining times add just (addto)
595 
596  // now put it all together
597  int addedLengthEta = 0;
598  int addedLengthPhi = 0;
599  int startIndexEta = mineta;
600  int startIndexPhi;
601  int endIndexEta = 0;
602  int endIndexPhi;
603  for (int i=0; i < numSubRegEta; i++)
604  {
605  addedLengthEta = regLength + addtoEta + addtomoreEta/abs(addtomoreEta)*(i<abs(addtomoreEta));
606  endIndexEta = startIndexEta + addedLengthEta - 1;
607 
608  startIndexPhi = minphi;
609  endIndexPhi = 0;
610  for (int j=0; j < numSubRegPhi; j++)
611  {
612  addedLengthPhi = regLength + addtoPhi + addtomorePhi/abs(addtomorePhi)*(j<abs(addtomorePhi));
613  endIndexPhi = startIndexPhi + addedLengthPhi - 1;
614 
615  regMinPhi.push_back(startIndexPhi - regFrame*(j!=0) );
616  regMaxPhi.push_back(endIndexPhi + regFrame*(j!=(numSubRegPhi-1)) );
617  regMinEta.push_back(startIndexEta - regFrame*(i!=0) );
618  regMaxEta.push_back(endIndexEta + regFrame*(i!=(numSubRegEta-1)) );
619 
620  startIndexPhi = endIndexPhi + 1;
621  }
622  startIndexEta = endIndexEta + 1;
623  }
624 
625 // // print it all
626 // std::cout << "Householder::makeRegions created the following regions for calibration:" << std::endl;
627 // for (int i=0; i<regMinEta.size(); i++)
628 // std::cout << "Region " << i << ": eta = " << regMinEta[i] << " to " << regMaxEta[i] << ", phi = " << regMinPhi[i] << " to " << regMaxPhi[i] << std::endl;
629 
630 }
void solve(std::vector< float > &y)
std::vector< float > recalibrateEvent(const std::vector< float > &eventSquare, const int &maxCeta, const int &maxCphi, const std::vector< float > &recalibrateVector)
Recalibrate before next iteration: give previous solution vector as argument.
void makeRegions(const int &regLength)
std::vector< float > iterate(const std::vector< std::vector< float > > &eventMatrix, const std::vector< int > &VmaxCeta, const std::vector< int > &VmaxCphi, const std::vector< float > &energyVector, const int &nIter, const bool &normalizeFlag=false)
T sqrt(T t)
Definition: SSEVec.h:18
int indexSqr2Reg(const int &sqrIndex, const int &maxCeta, const int &maxCphi)
Method to translate from square indices to region indices.
std::vector< std::vector< float > > eventMatrixProc
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< std::vector< float > > eventMatrixOrig
int k[5][pyjets_maxn]
std::vector< float > energyVectorProc
std::vector< float > runRegional(const std::vector< std::vector< float > > &eventMatrix, const std::vector< int > &VmaxCeta, const std::vector< int > &VmaxCphi, const std::vector< float > &energyVector, const int &nIter, const int &regLength=5)
std::vector< std::vector< float > > unzipMatrix(const std::vector< std::vector< float > > &eventMatrix, const std::vector< int > &VmaxCeta, const std::vector< int > &VmaxCphi)
Unzips the skimmed matrix into a full matrix.
HouseholderDecomposition(int squareMode_=5, int mineta_=1, int maxeta_=85, int minphi_=1, int maxphi_=20)
Default constructor.