CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/MuonAnalysis/MomentumScaleCalibration/interface/CrossSectionHandler.h

Go to the documentation of this file.
00001 
00018 #include <vector>
00019 #include <numeric>
00020 
00021 #include "TString.h"
00022 #include "TMinuit.h"
00023 
00024 class CrossSectionHandler
00025 {
00026 public:
00027   CrossSectionHandler(const std::vector<double> & crossSection, const std::vector<int> & resfind) :
00028     parNum_(0),
00029     numberOfResonances_(resfind.size())
00030   {
00031     // The number of parameters is the number of fitted resonances minus 1
00032     std::vector<int>::const_iterator it = resfind.begin();
00033     for( ; it != resfind.end(); ++it ) {
00034       if( *it != 0 ) ++parNum_;
00035     }
00036     if( parNum_ > 0 ) parNum_ = parNum_ - 1;
00037 
00038     vars_.resize(parNum_);
00039 
00040     computeRelativeCrossSections(crossSection, resfind);
00041     imposeConstraint();
00042   }
00043 
00045   void addParameters(std::vector<double> & initpar)
00046   {
00047     std::vector<double>::const_iterator it = vars_.begin();
00048     for( ; it != vars_.end(); ++it ) {
00049       initpar.push_back(*it);
00050     }
00051   }
00052 
00054   void setParameters( double* Start, double* Step, double* Mini, double* Maxi, int* ind, TString* parname,
00055                       const std::vector<double> & parCrossSection, const std::vector<int> & parCrossSectionOrder,
00056                       const std::vector<int> & resfind )
00057   {
00058     computeRelativeCrossSections(parCrossSection, resfind);
00059     imposeConstraint();
00060 
00061     double thisStep[] = {0.001, 0.001, 0.001, 0.001, 0.001};
00062     TString thisParName[] = {"cross section var 1",
00063                              "cross section var 2",
00064                              "cross section var 3",
00065                              "cross section var 4",
00066                              "cross section var 5"};
00067     double thisMini[] = {0., 0., 0., 0., 0.};
00068     double thisMaxi[] = {1000., 1000., 1000., 1000., 1000.};
00069 
00070     // This is used to unlock the parameters in a given order. It is not
00071     // a TMinuit parameter, but a MuScleFit parameter.
00072     for( unsigned int iPar=0; iPar<numberOfResonances_; ++iPar ) {
00073       ind[iPar] = parCrossSectionOrder[iPar];
00074     }
00075 
00076     if( parNum_ > 0 ) {
00077       for( unsigned int iPar=0; iPar<parNum_; ++iPar ) {
00078         Start[iPar] = vars_[iPar];
00079         Step[iPar] = thisStep[iPar];
00080         Mini[iPar] = thisMini[iPar];
00081         Maxi[iPar] = thisMaxi[iPar];
00082         parname[iPar] = thisParName[iPar];
00083       }
00084     }
00085   }
00086 
00088   bool releaseParameters( TMinuit & rmin, const std::vector<int> & resfind, const std::vector<int> & parfix,
00089                           const int * ind, const int iorder, const unsigned int shift )
00090   {
00091     // Find the number of free cross section parameters in this iteration
00092     unsigned int freeParNum = 0;
00093     for( unsigned int ipar=0; ipar<numberOfResonances_; ++ipar ) {
00094       if( (parfix[shift+ipar]==0) && (ind[shift+ipar]<=iorder) && (resfind[ipar] == 1) ) {
00095         ++freeParNum;
00096       }
00097     }
00098     if( freeParNum > 0 ) {
00099       freeParNum = freeParNum - 1;
00100       // Free only the first (freeParNum-1) of the N-1 variables
00101       for( unsigned int i=0; i<freeParNum; ++i ) {
00102         rmin.Release( shift+i );
00103       }
00104       return true;
00105     }
00106     return false;
00107   }
00108 
00109   inline unsigned int parNum()
00110   {
00111     return parNum_;
00112   }
00113 
00115   std::vector<double> relativeCrossSections( const double * variables, const std::vector<int> & resfind )
00116   {
00117     // parNum_ is 0 in two cases:
00118     // 1) if only one resonance is being fitted, in which case the relative cross section is
00119     // fixed to one and there is no need to recompute it
00120     // 2) if no resonance is being fitted, in which case all the relative cross sections will
00121     // be set to 0.
00122     // In both cases there is no need to make the transformation of variables.
00123     if( parNum_ != 0 ) {
00124       double * partialProduct = new double[numberOfResonances_];
00125       double norm = 0.;
00126       // Loop on all relative cross sections (that are parNum_+1)
00127       for( unsigned int i=0; i<parNum_+1; ++i ) {
00128         partialProduct[i] = std::accumulate(variables, variables + i, 1., std::multiplies<double>());
00129         norm += partialProduct[i];
00130       }
00131       for( unsigned int i=0; i<parNum_+1; ++i ) {
00132         relativeCrossSectionVec_[i] = partialProduct[i]/norm;
00133       }
00134       delete[] partialProduct;
00135     }
00136 
00137     std::vector<double> allRelativeCrossSections;
00138     std::vector<int>::const_iterator it = resfind.begin();
00139     int smallerVectorIndex = 0;
00140     for( ; it != resfind.end(); ++it ) {
00141       if( *it == 0 ) {
00142         allRelativeCrossSections.push_back(0.);
00143       }
00144       else {
00145         allRelativeCrossSections.push_back(relativeCrossSectionVec_[smallerVectorIndex]);
00146         ++smallerVectorIndex;
00147       }
00148     }
00149 
00150     return allRelativeCrossSections;
00151   }
00152 
00153 protected:
00159   // void computeRelativeCrossSections(const double crossSection[], const std::vector<int> resfind, const unsigned int minRes, const unsigned int maxRes)
00160   void computeRelativeCrossSections(const std::vector<double> & crossSection, const std::vector<int> & resfind)
00161   {
00162     relativeCrossSectionVec_.clear();
00163     double normalization = 0.;
00164     for( unsigned int ires = 0; ires < resfind.size(); ++ires ) {
00165       if( resfind[ires] ) {
00166         normalization += crossSection[ires];
00167       }
00168     }
00169     if( normalization != 0. ) {
00170       for( unsigned int ires = 0; ires < resfind.size(); ++ires ) {
00171         if( resfind[ires] ) {
00172           relativeCrossSectionVec_.push_back(crossSection[ires]/normalization);
00173         }
00174       }
00175     }
00176   }
00177 
00179   void imposeConstraint()
00180   {
00181     if( parNum_ > 0 ) {
00182       for( unsigned int iVar = 0; iVar < parNum_; ++iVar ) {
00183         vars_[iVar] = relativeCrossSectionVec_[iVar+1]/relativeCrossSectionVec_[iVar];
00184       }
00185     }
00186   }
00187 
00188   // Data members
00189   std::vector<double> relativeCrossSectionVec_;
00190   std::vector<double> vars_;
00191   unsigned int parNum_;
00192   unsigned int numberOfResonances_;
00193 };