CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoParticleFlow/PFClusterTools/src/LinearCalibrator.cc

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFClusterTools/interface/LinearCalibrator.h"
00002 #include <cassert>
00003 #include <cmath>
00004 #include "TVector.h"
00005 #include "TDecompLU.h"
00006 #include "TDecompSVD.h"
00007 
00008 #include "TDecompBK.h"
00009 
00010 #include <iostream>
00011 
00012 using namespace pftools;
00013 
00014 /* These utility functions allow you to print matrices and vectors to a stream,
00015  * and copy and paste the output directly into Octave or Matlab
00016  */
00017 void printMat(std::ostream& s, const TMatrixD& input) {
00018         s << "\t[";
00019         for (int i(0); i < input.GetNrows(); i++) {
00020                 for (int j(0); j < input.GetNcols(); j++) {
00021                         s << input[i][j]<< ", \t";
00022                 }
00023                 if (i != (input.GetNrows() - 1)) {
00024                         s << ";\n";
00025                         s << "\t";
00026                 }
00027         }
00028         s << "\t]\n";
00029 }
00030 
00031 void printVec(std::ostream& s, const TVectorD& input) {
00032         s << "\t[";
00033         for (int i(0); i < input.GetNrows(); i++) {
00034                 s << input[i];
00035                 if (i != (input.GetNrows() - 1)) {
00036                         s << ",\n\t";
00037                 }
00038         }
00039         s << "\t]\n";
00040 }
00041 
00042 LinearCalibrator::LinearCalibrator() {
00043 
00044 }
00045 
00046 LinearCalibrator::~LinearCalibrator() {
00047 }
00048 LinearCalibrator* LinearCalibrator::clone() const {
00049         return new LinearCalibrator(*this);
00050 }
00051 
00052 LinearCalibrator::LinearCalibrator(const LinearCalibrator& lc) {
00053         myDetectorElements = lc.myDetectorElements;
00054         myParticleDeposits = lc.myParticleDeposits;
00055 }
00056 
00057 LinearCalibrator* LinearCalibrator::create() const {
00058         return new LinearCalibrator();
00059 }
00060 
00061 std::map<DetectorElementPtr, double> LinearCalibrator::getCalibrationCoefficientsCore()
00062                 throw(PFToolsException&) {
00063 //      std::cout << __PRETTY_FUNCTION__
00064 //                      << ": determining linear calibration coefficients...\n";
00065         if (!hasParticles()) {
00066                 //I have no particles to calibrate to - throw exception.
00067                 PFToolsException me("Calibrator has no particles for calibration!");
00068                 throw me;
00069         }
00070         //std::cout << "\tGetting eij matrix...\n";
00071         TMatrixD eij;
00072         TVectorD truthE;
00073         initEijMatrix(eij, truthE);
00074 
00075 //      std::cout << "\tEij matrix:\n";
00076 //      printMat(std::cout, eij);
00077 
00078         //std::cout << "\tGetting projections...\n";
00079         TVectorD proj;
00080         TMatrixD hess;
00081 
00082         getProjections(eij, proj, truthE);
00083         //std::cout << "\tProjections:\n";
00084         //printVec(std::cout, proj);
00085         getHessian(eij, hess, truthE);
00086 
00087         TDecompLU lu;
00088         lu.SetMatrix(hess);
00089         //std::cout << "\tHessian:\n";
00090         //printMat(std::cout, hess);
00091 
00092         lu.SetTol(1e-25);
00093         TMatrixD hessInv = lu.Invert();
00094         //std::cout <<"\tInverse Hessian:\n";
00095         //printMat(std::cout, hessInv);
00096         TVectorD calibsSolved(eij.GetNcols());
00097 
00098         bool ok(true);
00099         calibsSolved = lu.Solve(proj, ok);
00100         if (ok) {
00101                 //std::cout << "\tLU reports ok.\n";
00102         }
00103         else {
00104                 std::cout << "\tWARNING: LU reports NOT ok.\n";
00105                 //This usually happens when you've asked the calibrator to solve for the 'a' term, without including
00106                 //a dummy 'a' term in each particle deposit.
00107                 //Make sure you do
00108                 //Deposition dOffset(offset, eta, phi, 1.0);
00109                 //particle->addRecDeposition(dOffset);
00110                 //particle->addTruthDeposition(dOffset);
00111                 std::cout
00112                                 << "\tDid you forget to add a dummy offset deposition to each particle?\n";
00113                 std::cout << "\tThrowing an exception!"<< std::endl;
00114                 PFToolsException
00115                                 me("TDecompLU did not converge successfully when finding calibrations. Did you forget to add a dummy offset deposition to each particle?");
00116                 throw me;
00117         }
00118 
00119         //std::cout << "\tCalibrations: \n";
00120         //printVec(std::cout, calibsSolved);
00121 
00122         std::map<DetectorElementPtr, double> answers;
00123         for (std::map<DetectorElementPtr, unsigned>::iterator it =
00124                         myDetElIndex.begin(); it != myDetElIndex.end(); ++it) {
00125                 DetectorElementPtr de = (*it).first;
00126                 answers[de] = calibsSolved[(*it).second];
00127         }
00128         return answers;
00129 }
00130 
00131 void LinearCalibrator::initEijMatrix(TMatrixD& eij, TVectorD& truthE) {
00132         //std::cout << __PRETTY_FUNCTION__ << "\n";
00133         //std::cout << "\tGetting detector element indices...\n";
00134         populateDetElIndex();
00135         eij.Clear();
00136         eij.Zero();
00137 
00138         truthE.ResizeTo(myParticleDeposits.size());
00139         truthE.Zero();
00140 
00141         //First determine number of calibration constants.
00142 
00143         eij.ResizeTo(myParticleDeposits.size(), myDetElIndex.size());
00144 
00145         //loop over all particle deposits
00146         unsigned index(0);
00147         for (std::vector<ParticleDepositPtr>::const_iterator cit =
00148                         myParticleDeposits.begin(); cit != myParticleDeposits.end(); ++cit) {
00149                 ParticleDepositPtr p = *cit;
00150                 //get each of the relevant detector elements
00151 
00152                 for (std::vector<DetectorElementPtr>::const_iterator detElIt =
00153                                 myDetectorElements.begin(); detElIt != myDetectorElements.end(); ++detElIt) {
00154                         DetectorElementPtr de = *detElIt;
00155                         eij[index][myDetElIndex[de]] = p->getRecEnergy(de);
00156                         //truthE[p->getId()] += p->getTruthEnergy(de);
00157                 }
00158                 truthE[index] = p->getTruthEnergy();
00159                 ++index;
00160         }
00161 
00162 }
00163 
00164 TVectorD& LinearCalibrator::getProjections(const TMatrixD& eij, TVectorD& proj,
00165                 const TVectorD& truthE) const {
00166         //std::cout << __PRETTY_FUNCTION__ << "\n";
00167         proj.ResizeTo(eij.GetNcols());
00168         proj.Zero();
00169 
00170         for (int j(0); j < eij.GetNcols(); ++j) {
00171                 for (int i(0); i < eij.GetNrows(); ++i) {
00172                         proj[j] += eij[i][j] / truthE[i];
00173                 }
00174         }
00175 
00176         return proj;
00177 }
00178 
00179 TMatrixD& LinearCalibrator::getHessian(const TMatrixD& eij, TMatrixD& hess,
00180                 const TVectorD& truthE) const {
00181         //std::cout << __PRETTY_FUNCTION__ << "\n";
00182         unsigned nCalibs(eij.GetNcols());
00183         hess.ResizeTo(nCalibs, nCalibs);
00184         hess.Zero();
00185 
00186         for (unsigned i(0); i < nCalibs; ++i) {
00187                 for (unsigned j(0); j < nCalibs; ++j) {
00188                         for (int n(0); n < eij.GetNrows(); ++n) {
00189                                 hess[i][j] += eij[n][i] * eij[n][j]/ pow(truthE[n], 2.0);
00190                         }
00191                 }
00192         }
00193 
00194         return hess;
00195 }
00196 
00197 void LinearCalibrator::populateDetElIndex() {
00198         //reserve index = 0 for the constant term, if we're told to compute it
00199         unsigned index(0);
00200 
00201         myDetElIndex.clear();
00202         //loop over known detector elements, and assign a unique row/column index to each
00203         for (std::vector<DetectorElementPtr>::const_iterator cit =
00204                         myDetectorElements.begin(); cit != myDetectorElements.end(); ++cit) {
00205                 DetectorElementPtr de = *cit;
00206                 //std::cout << "\tGot element: "<< *de;
00207                 //check we don't have duplicate detector elements
00208                 if (myDetElIndex.count(de) == 0) {
00209                         myDetElIndex[de] = index;
00210                         ++index;
00211                 }
00212         }
00213 
00214 }
00215