CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/MuonAnalysis/MomentumScaleCalibration/plugins/MuScleFit.cc

Go to the documentation of this file.
00001 //  \class MuScleFit
00002 //  Fitter of momentum scale and resolution from resonance decays to muon track pairs
00003 //
00004 //  $Date: 2010/10/22 17:48:07 $
00005 //  $Revision: 1.98 $
00006 //  \author R. Bellan, C.Mariotti, S.Bolognesi - INFN Torino / T.Dorigo, M.De Mattia - INFN Padova
00007 //
00008 //  Recent additions:
00009 //  - several parameters allow a more flexible use, tests, and control handles
00010 //    for the likelihood. In particular, a set of integers controls the order
00011 //    with which parameters are released; another controls which parameters are
00012 //    fixed. A function allows to smear momenta and angles of muons from the
00013 //    resonance before any correction, using a set of random numbers generated
00014 //    once and for all in the constructor (this way the smearing remains the same
00015 //    for any given muon no matter how many times one loops and what corrections
00016 //    one applies).
00017 //    For a correct use of these flags, please see the function minimizeLikelihood() in
00018 //    MuScleFitUtils.cc
00019 //  - the fit now allows to extract resolution functions simultaneously with the
00020 //    momentum scale. So far a simple parametrization
00021 //    of muon momentum resolution and angle resolution has been implemented, but
00022 //    extensions are straightforward.
00023 //  - It is however advisable to fit separately resolution and scale. The suggested
00024 //    course of action is:
00025 //    1) fit the scale with a simple parametrization
00026 //    2) check results, fit with more complicated forms
00027 //    3) verify which is a sufficiently accurate description of the data
00028 //    4) fix scale parameters and fit for the resolution
00029 //    5) go back to fitting the scale with resolution parameters fixed to fitted values
00030 //  - Also note that resolution fits may fail to converge due to instability of the
00031 //    probability distribution to the limit of large widths. Improvements here are
00032 //    advisable.
00033 //  - The treatment of signal windows in the Y region
00034 //    has to be refined because of overlaps. More work is needed here, assigning a different
00035 //    weight to different hypothesis of the resonance producing a given mass, if there are
00036 //    multiple candidates.
00037 //  - Also, larger windows are to be allowed for fits to SA muons.
00038 //  - File Probs_1000.root contains the probability distribution of lorentzians convoluted
00039 //    with gaussian smearing functions, for the six resonances. A 1000x1000 grid
00040 //    in mass,sigma has been computed (using root macro Probs.C).
00041 //    A wider interval of masses for each resonance should be computed, to be used for standalone muons
00042 //
00043 //
00044 //  Notes on additions, TD 31/3/08
00045 //
00046 //  - background model: at least a couple of different models, with two parameters,
00047 //    should be included in the fitting procedure such that the function massprob(),
00048 //    which produces the probability in the likelihood computation, incorporates the
00049 //    probability that the event is from background. That is, if the fitting function
00050 //    knows the shape of the mass spectrum ( say, a falling exponential plus a gaussian
00051 //    signal) it becomes possible to fit the scale together with the background shape
00052 //    and normalization parameters. Of course, one should do one thing at a time: first
00053 //    a scale fit, then a shape fit with scale parameters fixed, and then a combined
00054 //    fit. Convergence issues should be handled case by case.
00055 //  - The correct implementation of the above idea requires a reorganization of pass
00056 //    parameters (in the cfg) and fit parameters. The user has to be able to smear,
00057 //    bias, fix parameters, choose scale fitting functions, resolution fitting functions,
00058 //    and background functions. It should be possible to separate the fit functions from
00059 //    the biasing ones, which would allow a more thorough testing.
00060 //  - all the above can be obtained by making the .cfg instructions heavier. Since this
00061 //    is a routine operated by experts only, it is a sensible choice.
00062 //  - One should thus envision the following:
00063 //      1) a set of parameters controlling the biasing function: parBias()
00064 //      2) a set of parameters controlling the smearing function: parSmear()
00065 //      3) a set of parameters to define resolution modeling and initial values: parResol()
00066 //      3b) parResol() gets fix and order bits by parResolFix() and parResolOrder()
00067 //      4) a set of parameters to define scale modeling and initial values: parScale()
00068 //      4b) parScale() gets fix and order bits by parScaleFix() and parScaleOrder()
00069 //      5) a set of parameters controlling the background shape and normalization: parNorm()
00070 //      5b) parNorm() gets fix and order bits by parNormFix() and parNormOrder()
00071 //    The likelihood parameters then become a vector which is dynamically composed of
00072 //    sets 3), 4), and 5): parval() = parResol()+parScale()+parNorm()
00073 //  - In order to study better the likelihood behavior it would be advisable to introduce
00074 //    some histogram filling on the last iteration of the likelihood. It is not clear
00075 //    how best to achieve that: probably the simplest way is to make a histogram filling
00076 //    function run just after the likelihood computation, such that the best value of the
00077 //    fit parameters is used.
00078 //  - The muon pair which we call our resonance must be chosen in a way which does not
00079 //    bias our likelihood: we cannot just choose the pair closest to a resonance.
00080 //
00081 //
00082 //    Notes on additions, T.Dorigo 22/12/2008
00083 //    ---------------------------------------
00084 //
00085 //  - File Probs_new_1000_CTEQ.root now contains a set of 24 additional two-dim histograms,
00086 //    defining the probability distribution of Z boson decays as a function of measured mass
00087 //    and expected sigma in 24 different bins of Z rapidity, extracted from CTEQ 6 PDF (at
00088 //    Leading Order) from the convolution in the factorization integral. See programs CTEQ.cpp
00089 //    and Fits.C.
00090 //  - The probability for Z boson events now thus depends on the measured rapidity of the dimuon
00091 //    system. All functions in file MuScleFitUtils.cc have been suitably changed.
00092 //
00093 // ----------------------------------------------------------------------------------
00094 //    Modifications by M. De Mattia 13/3/2009
00095 //    ---------------------------------------
00096 //  - The histograms map was moved to a base class (MuScleFitBase) from which this one inherits.
00097 //
00098 //    Modifications by M. De Mattia 20/7/2009
00099 //    ---------------------------------------
00100 //  - Reworked background fit based on ranges. See comments in the code for more details.
00101 // ---------------------------------------------------------------------------------------------
00102 
00103 #include "MuScleFit.h"
00104 #include "MuonAnalysis/MomentumScaleCalibration/interface/Histograms.h"
00105 #include "MuonAnalysis/MomentumScaleCalibration/interface/MuScleFitPlotter.h"
00106 #include "FWCore/Framework/interface/MakerMacros.h"
00107 #include "FWCore/Framework/interface/Frameworkfwd.h"
00108 #include "FWCore/Framework/interface/Event.h"
00109 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00110 
00111 #include "HepPDT/defs.h"
00112 #include "HepPDT/TableBuilder.hh"
00113 #include "HepPDT/ParticleDataTable.hh"
00114 
00115 #include "HepMC/GenParticle.h"
00116 #include "HepMC/GenEvent.h"
00117 // #include "SimDataFormats/HepMCProduct/interface/HepMCProduct.h"
00118 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
00119 
00120 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
00121 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
00122 #include "SimDataFormats/Vertex/interface/SimVertexContainer.h"
00123 
00124 #include "TFile.h"
00125 #include "TTree.h"
00126 #include "TMinuit.h"
00127 #include <vector>
00128 
00129 #include "DataFormats/Common/interface/TriggerResults.h"
00130 #include "HLTrigger/HLTcore/interface/HLTConfigProvider.h"
00131 
00132 // To use callgrind for code profiling uncomment also the following define.
00133 // #define USE_CALLGRIND
00134 
00135 #ifdef USE_CALLGRIND
00136 #include "valgrind/callgrind.h"
00137 #endif
00138 
00139 #include "MuonAnalysis/MomentumScaleCalibration/interface/Functions.h"
00140 #include "MuonAnalysis/MomentumScaleCalibration/interface/RootTreeHandler.h"
00141 
00142 // To read likelihood distributions from the database.
00143         //#include "CondFormats/RecoMuonObjects/interface/MuScleFitLikelihoodPdf.h"
00144         //#include "CondFormats/DataRecord/interface/MuScleFitLikelihoodPdfRcd.h"
00145 
00146 // Constructor
00147 // -----------
00148 MuScleFit::MuScleFit( const edm::ParameterSet& pset ) :
00149   MuScleFitBase( pset ),
00150   totalEvents_(0)
00151 {
00152   MuScleFitUtils::debug = debug_;
00153   if (debug_>0) std::cout << "[MuScleFit]: Constructor" << std::endl;
00154 
00155   if ((theMuonType_<-4 || theMuonType_>5) && theMuonType_<10) {
00156     std::cout << "[MuScleFit]: Unknown muon type! Aborting." << std::endl;
00157     abort();
00158   }
00159 
00160   loopCounter = 0;
00161 
00162   // Boundaries for h-function computation (to be improved!)
00163   // -------------------------------------------------------
00164   minResMass_hwindow[0] = 76.;
00165   maxResMass_hwindow[0] = 106.;
00166   minResMass_hwindow[1] = 10.15;
00167   maxResMass_hwindow[1] = 10.55;
00168   minResMass_hwindow[2] = 9.8;
00169   maxResMass_hwindow[2] = 10.2;
00170   minResMass_hwindow[3] = 9.25;
00171   maxResMass_hwindow[3] = 9.65;
00172   minResMass_hwindow[4] = 3.58;
00173   maxResMass_hwindow[4] = 3.78;
00174   minResMass_hwindow[5] = 3.0;
00175   maxResMass_hwindow[5] = 3.2;
00176 
00177   // Max number of loops (if > 2 then try to minimize likelihood more than once)
00178   // ---------------------------------------------------------------------------
00179   maxLoopNumber = pset.getUntrackedParameter<int>("maxLoopNumber", 2);
00180   fastLoop = pset.getUntrackedParameter<bool>("FastLoop", true);
00181 
00182   // Selection of fits according to loop
00183   MuScleFitUtils::doResolFit = pset.getParameter<std::vector<int> >("doResolFit");
00184   MuScleFitUtils::doScaleFit = pset.getParameter<std::vector<int> >("doScaleFit");
00185   MuScleFitUtils::doCrossSectionFit = pset.getParameter<std::vector<int> >("doCrossSectionFit");
00186   MuScleFitUtils::doBackgroundFit = pset.getParameter<std::vector<int> >("doBackgroundFit");
00187 
00188   // Bias and smear types
00189   // --------------------
00190   int biasType = pset.getParameter<int>("BiasType");
00191   MuScleFitUtils::BiasType = biasType;
00192   // No error, the scale functions are used also for the bias
00193   MuScleFitUtils::biasFunction = scaleFunctionVecService( biasType );
00194   int smearType = pset.getParameter<int>("SmearType");
00195   MuScleFitUtils::SmearType = smearType;
00196   MuScleFitUtils::smearFunction = smearFunctionService( smearType );
00197 
00198   // Fit types
00199   // ---------
00200   int resolFitType = pset.getParameter<int>("ResolFitType");
00201   MuScleFitUtils::ResolFitType = resolFitType;
00202   MuScleFitUtils::resolutionFunction = resolutionFunctionService( resolFitType );
00203   MuScleFitUtils::resolutionFunctionForVec = resolutionFunctionVecService( resolFitType );
00204   int scaleType = pset.getParameter<int>("ScaleFitType");
00205   MuScleFitUtils::ScaleFitType = scaleType;
00206   MuScleFitUtils::scaleFunction = scaleFunctionService( scaleType );
00207   MuScleFitUtils::scaleFunctionForVec = scaleFunctionVecService( scaleType );
00208 
00209   // Initial parameters values
00210   // -------------------------
00211   MuScleFitUtils::parBias         = pset.getParameter<std::vector<double> >("parBias");
00212   MuScleFitUtils::parSmear        = pset.getParameter<std::vector<double> >("parSmear");
00213   MuScleFitUtils::parResol        = pset.getParameter<std::vector<double> >("parResol");
00214   MuScleFitUtils::parScale        = pset.getParameter<std::vector<double> >("parScale");
00215   MuScleFitUtils::parCrossSection = pset.getParameter<std::vector<double> >("parCrossSection");
00216   MuScleFitUtils::parBgr          = pset.getParameter<std::vector<double> >("parBgr");
00217   MuScleFitUtils::parResolFix        = pset.getParameter<std::vector<int> >("parResolFix");
00218   MuScleFitUtils::parScaleFix        = pset.getParameter<std::vector<int> >("parScaleFix");
00219   MuScleFitUtils::parCrossSectionFix = pset.getParameter<std::vector<int> >("parCrossSectionFix");
00220   MuScleFitUtils::parBgrFix          = pset.getParameter<std::vector<int> >("parBgrFix");
00221   MuScleFitUtils::parResolOrder        = pset.getParameter<std::vector<int> >("parResolOrder");
00222   MuScleFitUtils::parScaleOrder        = pset.getParameter<std::vector<int> >("parScaleOrder");
00223   MuScleFitUtils::parCrossSectionOrder = pset.getParameter<std::vector<int> >("parCrossSectionOrder");
00224   MuScleFitUtils::parBgrOrder          = pset.getParameter<std::vector<int> >("parBgrOrder");
00225 
00226   MuScleFitUtils::resfind     = pset.getParameter<std::vector<int> >("resfind");
00227   MuScleFitUtils::FitStrategy = pset.getParameter<int>("FitStrategy");
00228 
00229   // Option to skip unnecessary stuff
00230   // --------------------------------
00231   MuScleFitUtils::speedup = pset.getParameter<bool>("speedup");
00232 
00233   // Option to skip simTracks comparison
00234   compareToSimTracks_ = pset.getParameter<bool>("compareToSimTracks");
00235   simTracksCollection_ = pset.getUntrackedParameter<edm::InputTag>("SimTracksCollection", edm::InputTag("g4SimHits"));
00236 
00237   triggerResultsLabel_ = pset.getUntrackedParameter<std::string>("TriggerResultsLabel");
00238   triggerResultsProcess_ = pset.getUntrackedParameter<std::string>("TriggerResultsProcess");
00239   triggerPath_ = pset.getUntrackedParameter<std::string>("TriggerPath");
00240   negateTrigger_ = pset.getUntrackedParameter<bool>("NegateTrigger", false);
00241   saveAllToTree_ = pset.getUntrackedParameter<bool>("SaveAllToTree", false);
00242 
00243   PATmuons_ = pset.getUntrackedParameter<bool>("PATmuons", false);
00244   genParticlesName_ = pset.getUntrackedParameter<std::string>("GenParticlesName", "genParticles");
00245 
00246   // Use the probability file or not. If not it will perform a simpler selection taking the muon pair with
00247   // invariant mass closer to the pdf value and will crash if some fit is attempted.
00248   MuScleFitUtils::useProbsFile_ = pset.getUntrackedParameter<bool>("UseProbsFile", true);
00249 
00250   // This must be set to true if using events generated with Sherpa
00251   MuScleFitUtils::sherpa_ = pset.getUntrackedParameter<bool>("Sherpa", false);
00252 
00253   MuScleFitUtils::rapidityBinsForZ_ = pset.getUntrackedParameter<bool>("RapidityBinsForZ", true);
00254 
00255   // Set the cuts on muons to be used in the fit
00256   MuScleFitUtils::maxMuonPt_ = pset.getUntrackedParameter<double>("MaxMuonPt", 100000000.);
00257   MuScleFitUtils::minMuonPt_ = pset.getUntrackedParameter<double>("MinMuonPt", 0.);
00258   MuScleFitUtils::minMuonEtaFirstRange_ = pset.getUntrackedParameter<double>("MinMuonEtaFirstRange", -6.);
00259   MuScleFitUtils::maxMuonEtaFirstRange_ = pset.getUntrackedParameter<double>("MaxMuonEtaFirstRange", 6.);
00260   MuScleFitUtils::minMuonEtaSecondRange_ = pset.getUntrackedParameter<double>("MinMuonEtaSecondRange", -100.);
00261   MuScleFitUtils::maxMuonEtaSecondRange_ = pset.getUntrackedParameter<double>("MaxMuonEtaSecondRange", 100.);
00262 
00263   MuScleFitUtils::debugMassResol_ = pset.getUntrackedParameter<bool>("DebugMassResol", false);
00264   // MuScleFitUtils::massResolComponentsStruct MuScleFitUtils::massResolComponents;
00265 
00266   // Check for parameters consistency
00267   // it will abort in case of errors.
00268   checkParameters();
00269 
00270   // Generate array of gaussian-distributed numbers for smearing
00271   // -----------------------------------------------------------
00272   if (MuScleFitUtils::SmearType>0) {
00273     std::cout << "[MuScleFit-Constructor]: Generating random values for smearing" << std::endl;
00274     TF1 G("G", "[0]*exp(-0.5*pow(x,2))", -5., 5.);
00275     double norm = 1/sqrt(2*TMath::Pi());
00276     G.SetParameter (0,norm);
00277     for (int i=0; i<10000; i++) {
00278       for (int j=0; j<7; j++) {
00279         MuScleFitUtils::x[j][i] = G.GetRandom();
00280       }
00281     }
00282   }
00283   MuScleFitUtils::goodmuon = 0;
00284 
00285   if(theMuonType_ > 0 &&  theMuonType_ < 4) {
00286     MuScleFitUtils::MuonTypeForCheckMassWindow = theMuonType_-1;
00287     MuScleFitUtils::MuonType = theMuonType_-1;
00288   }
00289   else if(theMuonType_ == 4 || theMuonType_ >= 10 || theMuonType_==-1 || theMuonType_==-2 || theMuonType_==-3 || theMuonType_==-4) {
00290     MuScleFitUtils::MuonTypeForCheckMassWindow = 2;
00291     MuScleFitUtils::MuonType = 2;
00292   }
00293   else{
00294     std::cout<<"Wrong muon type "<<theMuonType_<<std::endl;
00295     exit(1);
00296   }
00297 
00298   // When using standalone muons switch to the single Z pdf
00299   if( theMuonType_ == 2 ) {
00300     MuScleFitUtils::rapidityBinsForZ_ = false;
00301   }
00302 
00303   // Initialize ResMaxSigma And ResHalfWidth - 0 = global, 1 = SM, 2 = tracker
00304   // -------------------------------------------------------------------------
00305   MuScleFitUtils::massWindowHalfWidth[0][0] = 20.;
00306   MuScleFitUtils::massWindowHalfWidth[0][1] = 0.5;
00307   MuScleFitUtils::massWindowHalfWidth[0][2] = 0.5;
00308   MuScleFitUtils::massWindowHalfWidth[0][3] = 0.5;
00309   MuScleFitUtils::massWindowHalfWidth[0][4] = 0.2;
00310   MuScleFitUtils::massWindowHalfWidth[0][5] = 0.2;
00311   MuScleFitUtils::massWindowHalfWidth[1][0] = 50.;
00312   MuScleFitUtils::massWindowHalfWidth[1][1] = 2.5;
00313   MuScleFitUtils::massWindowHalfWidth[1][2] = 2.5;
00314   MuScleFitUtils::massWindowHalfWidth[1][3] = 2.5;
00315   MuScleFitUtils::massWindowHalfWidth[1][4] = 1.5;
00316   MuScleFitUtils::massWindowHalfWidth[1][5] = 1.5;
00317   MuScleFitUtils::massWindowHalfWidth[2][0] = 20.;
00318   MuScleFitUtils::massWindowHalfWidth[2][1] = 0.5;
00319   MuScleFitUtils::massWindowHalfWidth[2][2] = 0.5;
00320   MuScleFitUtils::massWindowHalfWidth[2][3] = 0.5;
00321   MuScleFitUtils::massWindowHalfWidth[2][4] = 0.2;
00322   MuScleFitUtils::massWindowHalfWidth[2][5] = 0.2;
00323 
00324   muonSelector_.reset(new MuScleFitMuonSelector(theMuonLabel_, theMuonType_, PATmuons_,
00325                                                 MuScleFitUtils::resfind,
00326                                                 MuScleFitUtils::speedup, genParticlesName_,
00327                                                 compareToSimTracks_, simTracksCollection_,
00328                                                 MuScleFitUtils::sherpa_, debug_));
00329 
00330   MuScleFitUtils::backgroundHandler = new BackgroundHandler( pset.getParameter<std::vector<int> >("BgrFitType"),
00331                                                              pset.getParameter<std::vector<double> >("LeftWindowBorder"),
00332                                                              pset.getParameter<std::vector<double> >("RightWindowBorder"),
00333                                                              MuScleFitUtils::ResMass,
00334                                                              MuScleFitUtils::massWindowHalfWidth[MuScleFitUtils::MuonTypeForCheckMassWindow] );
00335 
00336   MuScleFitUtils::crossSectionHandler = new CrossSectionHandler( MuScleFitUtils::parCrossSection, MuScleFitUtils::resfind );
00337 
00338   // Build cross section scale factors
00339   // MuScleFitUtils::resfind
00340 
00341   MuScleFitUtils::normalizeLikelihoodByEventNumber_ = pset.getUntrackedParameter<bool>("NormalizeLikelihoodByEventNumber", true);
00342   if(debug_>0) std::cout << "End of MuScleFit constructor" << std::endl;
00343 
00344   inputRootTreeFileName_ = pset.getParameter<std::string>("InputRootTreeFileName");
00345   outputRootTreeFileName_ = pset.getParameter<std::string>("OutputRootTreeFileName");
00346   maxEventsFromRootTree_ = pset.getParameter<int>("MaxEventsFromRootTree");
00347 
00348   MuScleFitUtils::startWithSimplex_ = pset.getParameter<bool>("StartWithSimplex");
00349   MuScleFitUtils::computeMinosErrors_ = pset.getParameter<bool>("ComputeMinosErrors");
00350   MuScleFitUtils::minimumShapePlots_ = pset.getParameter<bool>("MinimumShapePlots");
00351 
00352   beginOfJobInConstructor();
00353 }
00354 
00355 // Destructor
00356 // ----------
00357 MuScleFit::~MuScleFit () {
00358   if (debug_>0) std::cout << "[MuScleFit]: Destructor" << std::endl;
00359   std::cout << "Total number of analyzed events = " << totalEvents_ << std::endl;
00360 
00361   if( !(outputRootTreeFileName_.empty()) ) {
00362     // Save the events to a root tree unless we are reading from the edm root file and the SavedPair size is different from the totalEvents_
00363     if( !(inputRootTreeFileName_.empty() && (int(MuScleFitUtils::SavedPair.size()) != totalEvents_)) ) {
00364       std::cout << "Saving muon pairs to root tree" << std::endl;
00365       RootTreeHandler rootTreeHandler;
00366       if( MuScleFitUtils::speedup ) {
00367         // rootTreeHandler.writeTree(outputRootTreeFileName_, &(MuScleFitUtils::SavedPair), theMuonType_, 0, saveAllToTree_);
00368         rootTreeHandler.writeTree(outputRootTreeFileName_, &(muonPairs_), theMuonType_, 0, saveAllToTree_);
00369       }
00370       else {
00371         // rootTreeHandler.writeTree(outputRootTreeFileName_, &(MuScleFitUtils::SavedPair), theMuonType_, &(MuScleFitUtils::genPair), saveAllToTree_ );
00372         rootTreeHandler.writeTree(outputRootTreeFileName_, &(muonPairs_), theMuonType_, &(genMuonPairs_), saveAllToTree_ );
00373       }
00374     }
00375     else {
00376       std::cout << "ERROR: events in the vector = " << MuScleFitUtils::SavedPair.size() << " != totalEvents = " << totalEvents_ << std::endl;
00377     }
00378   }
00379 }
00380 
00381 // Begin job
00382 // ---------
00383 void MuScleFit::beginOfJobInConstructor()
00384 // void MuScleFit::beginOfJob ()
00385 // void MuScleFit::beginOfJob( const edm::EventSetup& eventSetup )
00386 {
00387   if (debug_>0) std::cout << "[MuScleFit]: beginOfJob" << std::endl;
00388   //if(maxLoopNumber>1)
00389   if( MuScleFitUtils::useProbsFile_ ) {
00390     readProbabilityDistributionsFromFile();
00391   }
00392 
00393   if (debug_>0) std::cout << "[MuScleFit]: beginOfJob" << std::endl;
00394 
00395   // Create the root file
00396   // --------------------
00397   for (unsigned int i=0; i<(maxLoopNumber); i++) {
00398     std::stringstream ss;
00399     ss << i;
00400     std::string rootFileName = ss.str() + "_" + theRootFileName_;
00401     theFiles_.push_back (new TFile(rootFileName.c_str(), "RECREATE"));
00402   }
00403   if (debug_>0) std::cout << "[MuScleFit]: Root file created" << std::endl;
00404 
00405   std::cout << "creating plotter" << std::endl;
00406   plotter = new MuScleFitPlotter(theGenInfoRootFileName_);
00407   plotter->debug = debug_;
00408 }
00409 
00410 // End of job method
00411 // -----------------
00412 void MuScleFit::endOfJob () {
00413   if (debug_>0) std::cout << "[MuScleFit]: endOfJob" << std::endl;
00414 }
00415 
00416 // New loop
00417 // --------
00418 void MuScleFit::startingNewLoop( unsigned int iLoop )
00419 {
00420   if (debug_>0) std::cout << "[MuScleFit]: Starting loop # " << iLoop << std::endl;
00421 
00422   // Number of muons used
00423   // --------------------
00424   MuScleFitUtils::goodmuon = 0;
00425 
00426   // Counters for problem std::cout-ing
00427   // -----------------------------
00428   MuScleFitUtils::counter_resprob = 0;
00429 
00430   // Create the root file
00431   // --------------------
00432   fillHistoMap(theFiles_[iLoop], iLoop);
00433 
00434   loopCounter = iLoop;
00435   MuScleFitUtils::loopCounter = loopCounter;
00436 
00437   iev = 0;
00438   MuScleFitUtils::iev_ = 0;
00439 
00440   MuScleFitUtils::oldNormalization_ = 0;
00441 }
00442 
00443 // End of loop routine
00444 // -------------------
00445 edm::EDLooper::Status MuScleFit::endOfLoop( const edm::EventSetup& eventSetup, unsigned int iLoop )
00446 {
00447   unsigned int iFastLoop = 1;
00448 
00449   // Read the events from the root tree if requested
00450   if( !(inputRootTreeFileName_.empty()) ) {
00451     selectMuons(maxEventsFromRootTree_, inputRootTreeFileName_);
00452     // When reading from local file all the loops are done here
00453     totalEvents_ = MuScleFitUtils::SavedPair.size();
00454     iFastLoop = 0;
00455   }
00456   else {
00457     endOfFastLoop(iLoop);
00458   }
00459 
00460   // If a fastLoop is required we do all the remaining iterations here
00461   if( fastLoop == true ) {
00462     for( ; iFastLoop<maxLoopNumber; ++iFastLoop ) {
00463 
00464       std::cout << "Starting fast loop number " << iFastLoop << std::endl;
00465 
00466       // In the first loop is called by the framework
00467       // if( iFastLoop > 0 ) {
00468       startingNewLoop(iFastLoop);
00469       // }
00470 
00471       // std::vector<std::pair<lorentzVector,lorentzVector> >::const_iterator it = MuScleFitUtils::SavedPair.begin();
00472       // for( ; it != SavedPair.end(); ++it ) {
00473       while( iev<totalEvents_ ) {
00474         if( iev%1000 == 0 ) {
00475           std::cout << "Fast looping on event number " << iev << std::endl;
00476         }
00477         // This reads muons from SavedPair using iev to keep track of the event
00478         duringFastLoop();
00479       }
00480       std::cout << "End of fast loop number " << iFastLoop << ". Ran on " << iev << " events" << std::endl;
00481       endOfFastLoop(iFastLoop);
00482     }
00483   }
00484 
00485   if (iFastLoop>=maxLoopNumber-1) {
00486     return kStop;
00487   } else {
00488     return kContinue;
00489   }
00490 }
00491 
00492 void MuScleFit::endOfFastLoop( const unsigned int iLoop )
00493 {
00494   // std::cout<< "Inside endOfFastLoop, iLoop = " << iLoop << " and loopCounter = " << loopCounter << std::endl;
00495 
00496   if( loopCounter == 0 ) {
00497     // plotter->writeHistoMap();
00498     // The destructor will call the writeHistoMap after the cd to the output file
00499     delete plotter;
00500   }
00501 
00502   std::cout << "Ending loop # " << iLoop << std::endl;
00503 
00504   // Write the histos to file
00505   // ------------------------
00506   // theFiles_[iLoop]->cd();
00507   writeHistoMap(iLoop);
00508 
00509   // Likelihood minimization to compute corrections
00510   // ----------------------------------------------
00511   // theFiles_[iLoop]->cd();
00512   TDirectory * likelihoodDir = theFiles_[iLoop]->mkdir("likelihood");
00513   likelihoodDir->cd();
00514   MuScleFitUtils::minimizeLikelihood();
00515 
00516   // ATTENTION, this was put BEFORE the minimizeLikelihood. Check for problems.
00517   theFiles_[iLoop]->Close();
00518   // ATTENTION: Check that this delete does not give any problem
00519   delete theFiles_[iLoop];
00520 
00521   // Clear the histos
00522   // ----------------
00523   clearHistoMap();
00524 }
00525 
00526 // Stuff to do during loop
00527 // -----------------------
00528 edm::EDLooper::Status MuScleFit::duringLoop( const edm::Event & event, const edm::EventSetup& eventSetup )
00529 {
00530   edm::Handle<edm::TriggerResults> triggerResults;
00531   event.getByLabel(edm::InputTag(triggerResultsLabel_.c_str(), "", triggerResultsProcess_.c_str()), triggerResults);
00532   //event.getByLabel(InputTag(triggerResultsLabel_),triggerResults);
00533   bool isFired = false;
00534 
00535   if(triggerPath_ == "")
00536     isFired = true;
00537   else if(triggerPath_ == "All"){
00538     isFired =triggerResults->accept();
00539     if(debug_>0)
00540       std::cout<<"Trigger "<<isFired<<std::endl;
00541   }
00542   else{
00543     bool changed;
00544     HLTConfigProvider hltConfig;
00545     hltConfig.init(event.getRun(), eventSetup, triggerResultsProcess_, changed);
00546     unsigned int triggerIndex( hltConfig.triggerIndex(triggerPath_) );
00547     // triggerIndex must be less than the size of HLTR or you get a CMSException: _M_range_check
00548     if (triggerIndex < triggerResults->size()) {
00549       isFired = triggerResults->accept(triggerIndex);
00550       if(debug_>0)
00551         std::cout<<triggerPath_<<" "<<isFired<<std::endl;
00552     }
00553   }
00554 
00555   if( negateTrigger_ && isFired ) return kContinue;
00556   else if( !(negateTrigger_) && !isFired ) return kContinue;
00557 
00558 #ifdef USE_CALLGRIND
00559   CALLGRIND_START_INSTRUMENTATION;
00560 #endif
00561 
00562   if (debug_>0) {
00563     std::cout << "[MuScleFit-duringLoop]: loopCounter = " << loopCounter
00564          << " Run: " << event.id().run() << " Event: " << event.id().event() << std::endl;
00565   }
00566 
00567   // On the first iteration we read the bank, otherwise we fetch the information from the muon tree
00568   // ------------------------------------ Important Note --------------------------------------- //
00569   // The fillMuonCollection method applies any smearing or bias to the muons, so we NEVER use
00570   // unbiased muons.
00571   // ----------------------------------------------------------------------------------------------
00572   if( loopCounter == 0 ) {
00573 
00574     if( !fastLoop || inputRootTreeFileName_.empty() ) {
00575       if( debug_ > 0 ) std::cout << "Reading from edm event" << std::endl;
00576       selectMuons(event);
00577       duringFastLoop();
00578       ++totalEvents_;
00579     }
00580   }
00581 
00582   return kContinue;
00583 
00584 #ifdef USE_CALLGRIND
00585   CALLGRIND_STOP_INSTRUMENTATION;
00586   CALLGRIND_DUMP_STATS;
00587 #endif
00588 }
00589 
00590 void MuScleFit::selectMuons(const edm::Event & event)
00591 {
00592   recMu1 = reco::Particle::LorentzVector(0,0,0,0);
00593   recMu2 = reco::Particle::LorentzVector(0,0,0,0);
00594 
00595   std::vector<reco::LeafCandidate> muons;
00596   muonSelector_->selectMuons(event, muons, genMuonPairs_, MuScleFitUtils::simPair, plotter);
00597   plotter->fillRec(muons);
00598 
00599   // Find the two muons from the resonance, and set ResFound bool
00600   // ------------------------------------------------------------
00601   std::pair<reco::Particle::LorentzVector, reco::Particle::LorentzVector> recMuFromBestRes =
00602     MuScleFitUtils::findBestRecoRes(muons);
00603 
00604   if (MuScleFitUtils::ResFound) {
00605     if (debug_>0) {
00606       std::cout <<std::setprecision(9)<< "Pt after findbestrecores: " << (recMuFromBestRes.first).Pt() << " "
00607            << (recMuFromBestRes.second).Pt() << std::endl;
00608       std::cout << "recMu1 = " << recMu1 << std::endl;
00609       std::cout << "recMu2 = " << recMu2 << std::endl;
00610     }
00611     recMu1 = recMuFromBestRes.first;
00612     recMu2 = recMuFromBestRes.second;
00613     if (debug_>0) {
00614       std::cout << "after recMu1 = " << recMu1 << std::endl;
00615       std::cout << "after recMu2 = " << recMu2 << std::endl;
00616       std::cout << "mu1.pt = " << recMu1.Pt() << std::endl;
00617       std::cout << "mu2.pt = " << recMu2.Pt() << std::endl;
00618     }
00619     MuScleFitUtils::SavedPair.push_back( std::make_pair( recMu1, recMu2 ) );
00620   } else {
00621     MuScleFitUtils::SavedPair.push_back( std::make_pair( lorentzVector(0.,0.,0.,0.), lorentzVector(0.,0.,0.,0.) ) );
00622   }
00623   // Save the events also in the external tree so that it can be saved later
00624   muonPairs_.push_back(MuonPair(MuScleFitUtils::SavedPair.back().first,
00625                                 MuScleFitUtils::SavedPair.back().second,
00626                                 event.run(), event.id().event()));
00627   // Fill the internal genPair tree from the external one
00628   MuScleFitUtils::genPair.push_back(std::make_pair( genMuonPairs_.back().mu1, genMuonPairs_.back().mu2 ));
00629 }
00630 
00631 void MuScleFit::selectMuons(const int maxEvents, const TString & treeFileName)
00632 {
00633   std::cout << "Reading muon pairs from Root Tree in " << treeFileName << std::endl;
00634   RootTreeHandler rootTreeHandler;
00635   if( MuScleFitUtils::speedup ) {
00636     rootTreeHandler.readTree(maxEvents, inputRootTreeFileName_, &(MuScleFitUtils::SavedPair), theMuonType_);
00637   }
00638   else {
00639     rootTreeHandler.readTree(maxEvents, inputRootTreeFileName_, &(MuScleFitUtils::SavedPair), theMuonType_, &(MuScleFitUtils::genPair));
00640   }
00641   // Now loop on all the pairs and apply any smearing and bias if needed
00642   std::vector<std::pair<lorentzVector,lorentzVector> >::iterator it = MuScleFitUtils::SavedPair.begin();
00643   for( ; it != MuScleFitUtils::SavedPair.end(); ++it ) {
00644 
00645     // Apply any cut if requested
00646     // Note that cuts here are only applied to already selected muons. They should not be used unless
00647     // you are sure that the difference is negligible (e.g. the number of events with > 2 muons is negligible).
00648     double pt1 = it->first.pt();
00649     // std::cout << "pt1 = " << pt1 << std::endl;
00650     double pt2 = it->second.pt();
00651     // std::cout << "pt2 = " << pt2 << std::endl;
00652     double eta1 = it->first.eta();
00653     // std::cout << "eta1 = " << eta1 << std::endl;
00654     double eta2 = it->second.eta();
00655     // std::cout << "eta2 = " << eta2 << std::endl;
00656     // If they don't pass the cuts set to null vectors
00657     if( !(pt1 > MuScleFitUtils::minMuonPt_ && pt1 < MuScleFitUtils::maxMuonPt_ &&
00658           pt2 > MuScleFitUtils::minMuonPt_ && pt2 < MuScleFitUtils::maxMuonPt_ &&
00659           ( (eta1 > MuScleFitUtils::minMuonEtaFirstRange_ && eta1 < MuScleFitUtils::maxMuonEtaFirstRange_ &&
00660              eta2 > MuScleFitUtils::minMuonEtaFirstRange_ && eta2 < MuScleFitUtils::maxMuonEtaFirstRange_) ||
00661             (eta1 > MuScleFitUtils::minMuonEtaSecondRange_ && eta1 < MuScleFitUtils::maxMuonEtaSecondRange_ &&
00662              eta2 > MuScleFitUtils::minMuonEtaSecondRange_ && eta2 < MuScleFitUtils::maxMuonEtaSecondRange_) ) ) ) {
00663       // std::cout << "removing muons not passing cuts" << std::endl;
00664       it->first = reco::Particle::LorentzVector(0,0,0,0);
00665       it->second = reco::Particle::LorentzVector(0,0,0,0);
00666     }
00667 
00668     // First is always mu-, second mu+
00669     if( (MuScleFitUtils::SmearType != 0) || (MuScleFitUtils::BiasType != 0) ) {
00670       applySmearing(it->first);
00671       applyBias(it->first, -1);
00672       applySmearing(it->second);
00673       applyBias(it->second, 1);
00674     }
00675   }
00676   plotter->fillRec(MuScleFitUtils::SavedPair);
00677   if( !(MuScleFitUtils::speedup) ) {
00678     plotter->fillGen(MuScleFitUtils::genPair);
00679   }
00680 }
00681 
00682 void MuScleFit::duringFastLoop()
00683 {
00684   // On loops>0 the two muons are directly obtained from the SavedMuon array
00685   // -----------------------------------------------------------------------
00686   MuScleFitUtils::ResFound = false;
00687   recMu1 = (MuScleFitUtils::SavedPair[iev].first);
00688   recMu2 = (MuScleFitUtils::SavedPair[iev].second);
00689   if (recMu1.Pt()>0 && recMu2.Pt()>0) {
00690     MuScleFitUtils::ResFound = true;
00691     if (debug_>0) std::cout << "Ev = " << iev << ": found muons in tree with Pt = "
00692                        << recMu1.Pt() << " " << recMu2.Pt() << std::endl;
00693   }
00694 
00695   if( debug_>0 ) std::cout << "About to start lik par correction and histo filling; ResFound is "
00696                     << MuScleFitUtils::ResFound << std::endl;
00697   // If resonance found, do the hard work
00698   // ------------------------------------
00699   if( MuScleFitUtils::ResFound ) {
00700 
00701     // Find weight and reference mass for this muon pair
00702     // -------------------------------------------------
00703     // The last parameter = true means that we want to use always the background window to compute the weight,
00704     // otherwise the probability will be filled only for the resonance region.
00705     double weight = MuScleFitUtils::computeWeight( (recMu1+recMu2).mass(), iev, true );
00706     if (debug_>0) {
00707       std::cout << "Loop #" << loopCounter << "Event #" << iev << ": before correction     Pt1 = "
00708            << recMu1.Pt() << " Pt2 = " << recMu2.Pt() << std::endl;
00709     }
00710     // For successive iterations, correct the muons only if the previous iteration was a scale fit.
00711     // --------------------------------------------------------------------------------------------
00712     if ( loopCounter>0 ) {
00713       if ( MuScleFitUtils::doScaleFit[loopCounter-1] ) {
00714         recMu1 = (MuScleFitUtils::applyScale(recMu1, MuScleFitUtils::parvalue[loopCounter-1], -1));
00715         recMu2 = (MuScleFitUtils::applyScale(recMu2, MuScleFitUtils::parvalue[loopCounter-1],  1));
00716       }
00717     }
00718     if (debug_>0) {
00719       std::cout << "Loop #" << loopCounter << "Event #" << iev << ": after correction      Pt1 = "
00720            << recMu1.Pt() << " Pt2 = " << recMu2.Pt() << std::endl;
00721     }
00722 
00723     reco::Particle::LorentzVector bestRecRes( recMu1+recMu2 );
00724 
00725     //Fill histograms
00726     //------------------
00727     mapHisto_["hRecBestMu"]->Fill(recMu1);
00728     mapHisto_["hRecBestMuVSEta"]->Fill(recMu1);
00729     mapHisto_["hRecBestMu"]->Fill(recMu2);
00730     mapHisto_["hRecBestMuVSEta"]->Fill(recMu2);
00731     mapHisto_["hDeltaRecBestMu"]->Fill(recMu1, recMu2);
00732     // Reconstructed resonance
00733     mapHisto_["hRecBestRes"]->Fill(bestRecRes, weight);
00734     mapHisto_["hRecBestResAllEvents"]->Fill(bestRecRes, 1.);
00735     // Fill histogram of Res mass vs muon variables
00736     mapHisto_["hRecBestResVSMu"]->Fill (recMu1, bestRecRes, -1);
00737     mapHisto_["hRecBestResVSMu"]->Fill (recMu2, bestRecRes, +1);
00738     // Fill histogram of Res mass vs Res variables
00739     mapHisto_["hRecBestResVSRes"]->Fill (bestRecRes, bestRecRes, +1);
00740 
00741     std::vector<double> * parval;
00742     std::vector<double> initpar;
00743     // Store a pointer to the vector of parameters of the last iteration, or the initial
00744     // parameters if this is the first iteration
00745     if (loopCounter==0) {
00746       initpar = MuScleFitUtils::parResol;
00747       initpar.insert( initpar.end(), MuScleFitUtils::parScale.begin(), MuScleFitUtils::parScale.end() );
00748       initpar.insert( initpar.end(), MuScleFitUtils::parCrossSection.begin(), MuScleFitUtils::parCrossSection.end() );
00749       initpar.insert( initpar.end(), MuScleFitUtils::parBgr.begin(), MuScleFitUtils::parBgr.end() );
00750       parval = &initpar;
00751     } else {
00752       parval = &(MuScleFitUtils::parvalue[loopCounter-1]);
00753     }
00754 
00755     //Compute pt resolution w.r.t generated and simulated muons
00756     //--------------------------------------------------------
00757     if( !MuScleFitUtils::speedup ) {
00758 
00759       //first is always mu-, second is always mu+
00760       if(checkDeltaR(MuScleFitUtils::genPair[iev].first,recMu1)) {
00761         fillComparisonHistograms( MuScleFitUtils::genPair[iev].first, recMu1, "Gen", -1 );
00762       }
00763       if(checkDeltaR(MuScleFitUtils::genPair[iev].second,recMu2)){
00764         fillComparisonHistograms( MuScleFitUtils::genPair[iev].second, recMu2, "Gen", +1 );
00765       }
00766       if( compareToSimTracks_ ) {
00767         //first is always mu-, second is always mu+
00768         if(checkDeltaR(MuScleFitUtils::simPair[iev].first,recMu1)){
00769           fillComparisonHistograms( MuScleFitUtils::simPair[iev].first, recMu1, "Sim", -1 );
00770         }
00771         if(checkDeltaR(MuScleFitUtils::simPair[iev].second,recMu2)){
00772           fillComparisonHistograms( MuScleFitUtils::simPair[iev].second, recMu2, "Sim", +1 );
00773         }
00774       }
00775     }
00776 
00777     // ATTENTION: this was done only when a matching was found. Moved it outside because, genInfo or not, we still want to see the resolution function
00778     // Fill also the resolution histogramsm using the resolution functions:
00779     // the parameters are those from the last iteration, as the muons up to this point have also the corrections from the same iteration.
00780     // Need to use a different array (ForVec), containing functors able to operate on std::vector<double>
00781     mapHisto_["hFunctionResolPt"]->Fill( recMu1, MuScleFitUtils::resolutionFunctionForVec->sigmaPt(recMu1.Pt(), recMu1.Eta(), *parval ), -1 );
00782     mapHisto_["hFunctionResolCotgTheta"]->Fill( recMu1, MuScleFitUtils::resolutionFunctionForVec->sigmaCotgTh(recMu1.Pt(), recMu1.Eta(), *parval ), -1 );
00783     mapHisto_["hFunctionResolPhi"]->Fill( recMu1, MuScleFitUtils::resolutionFunctionForVec->sigmaPhi(recMu1.Pt(), recMu1.Eta(), *parval ), -1 );
00784     mapHisto_["hFunctionResolPt"]->Fill( recMu2, MuScleFitUtils::resolutionFunctionForVec->sigmaPt(recMu2.Pt(), recMu2.Eta(), *parval ), +1 );
00785     mapHisto_["hFunctionResolCotgTheta"]->Fill( recMu2, MuScleFitUtils::resolutionFunctionForVec->sigmaCotgTh(recMu2.Pt(), recMu2.Eta(), *parval ), +1 );
00786     mapHisto_["hFunctionResolPhi"]->Fill( recMu2, MuScleFitUtils::resolutionFunctionForVec->sigmaPhi(recMu2.Pt(), recMu2.Eta(), *parval ), +1 );
00787 
00788     // Compute likelihood histograms
00789     // -----------------------------
00790     if( debug_ > 0 ) std::cout << "mass = " << bestRecRes.mass() << std::endl;
00791     if (weight!=0.) {
00792       double massResol;
00793       double prob;
00794       double deltalike;
00795       if (loopCounter==0) {
00796         std::vector<double> initpar;
00797         for (int i=0; i<(int)(MuScleFitUtils::parResol.size()); i++) {
00798           initpar.push_back(MuScleFitUtils::parResol[i]);
00799         }
00800         for (int i=0; i<(int)(MuScleFitUtils::parScale.size()); i++) {
00801           initpar.push_back(MuScleFitUtils::parScale[i]);
00802         }
00803 //      for (int i=0; i<(int)(MuScleFitUtils::parCrossSection.size()); i++) {
00804 //        initpar.push_back(MuScleFitUtils::parCrossSection[i]);
00805 //      }
00806         MuScleFitUtils::crossSectionHandler->addParameters(initpar);
00807 
00808         for (int i=0; i<(int)(MuScleFitUtils::parBgr.size()); i++) {
00809           initpar.push_back(MuScleFitUtils::parBgr[i]);
00810         }
00811         massResol = MuScleFitUtils::massResolution( recMu1, recMu2, initpar );
00812         prob      = MuScleFitUtils::massProb( bestRecRes.mass(), bestRecRes.Eta(), bestRecRes.Rapidity(), massResol, initpar, true );
00813       } else {
00814         massResol = MuScleFitUtils::massResolution( recMu1, recMu2,
00815                                                     MuScleFitUtils::parvalue[loopCounter-1] );
00816         prob      = MuScleFitUtils::massProb( bestRecRes.mass(), bestRecRes.Eta(), bestRecRes.Rapidity(),
00817                                               massResol, MuScleFitUtils::parvalue[loopCounter-1], true );
00818       }
00819       if( debug_ > 0 ) std::cout << "inside weight: mass = " << bestRecRes.mass() << ", prob = " << prob << std::endl;
00820       if (prob>0) {
00821         if( debug_ > 0 ) std::cout << "inside prob: mass = " << bestRecRes.mass() << ", prob = " << prob << std::endl;
00822 
00823         deltalike = log(prob)*weight; // NB maximum likelihood --> deltalike is maximized
00824         mapHisto_["hLikeVSMu"]->Fill(recMu1, deltalike);
00825         mapHisto_["hLikeVSMu"]->Fill(recMu2, deltalike);
00826         mapHisto_["hLikeVSMuMinus"]->Fill(recMu1, deltalike);
00827         mapHisto_["hLikeVSMuPlus"]->Fill(recMu2, deltalike);
00828 
00829         double recoMass = (recMu1+recMu2).mass();
00830         if( recoMass != 0 ) {
00831           // IMPORTANT: massResol is not a relative resolution
00832           mapHisto_["hResolMassVSMu"]->Fill(recMu1, massResol, -1);
00833           mapHisto_["hResolMassVSMu"]->Fill(recMu2, massResol, +1);
00834           mapHisto_["hFunctionResolMassVSMu"]->Fill(recMu1, massResol/recoMass, -1);
00835           mapHisto_["hFunctionResolMassVSMu"]->Fill(recMu2, massResol/recoMass, +1);
00836         }
00837 
00838         if( MuScleFitUtils::debugMassResol_ ) {
00839           mapHisto_["hdMdPt1"]->Fill(recMu1, MuScleFitUtils::massResolComponents.dmdpt1, -1);
00840           mapHisto_["hdMdPt2"]->Fill(recMu2, MuScleFitUtils::massResolComponents.dmdpt2, +1);
00841           mapHisto_["hdMdPhi1"]->Fill(recMu1, MuScleFitUtils::massResolComponents.dmdphi1, -1);
00842           mapHisto_["hdMdPhi2"]->Fill(recMu2, MuScleFitUtils::massResolComponents.dmdphi2, +1);
00843           mapHisto_["hdMdCotgTh1"]->Fill(recMu1, MuScleFitUtils::massResolComponents.dmdcotgth1, -1);
00844           mapHisto_["hdMdCotgTh2"]->Fill(recMu2, MuScleFitUtils::massResolComponents.dmdcotgth2, +1);
00845         }
00846 
00847         if( !MuScleFitUtils::speedup ) {
00848           double genMass = (MuScleFitUtils::genPair[iev].first + MuScleFitUtils::genPair[iev].second).mass();
00849           // Fill the mass resolution (computed from MC), we use the covariance class to compute the variance
00850           if( genMass != 0 ) {
00851             mapHisto_["hGenResVSMu"]->Fill((MuScleFitUtils::genPair[iev].first), (MuScleFitUtils::genPair[iev].first + MuScleFitUtils::genPair[iev].second), -1);
00852             mapHisto_["hGenResVSMu"]->Fill((MuScleFitUtils::genPair[iev].second), (MuScleFitUtils::genPair[iev].first + MuScleFitUtils::genPair[iev].second), +1);
00853             double diffMass = (recoMass - genMass)/genMass;
00854             // double diffMass = recoMass - genMass;
00855             // Fill if for both muons
00856             double pt1 = recMu1.pt();
00857             double eta1 = recMu1.eta();
00858             double pt2 = recMu2.pt();
00859             double eta2 = recMu2.eta();
00860             // This is to avoid nan
00861             if( diffMass == diffMass ) {
00862               // Mass relative difference vs Pt and Eta. To be used to extract the true mass resolution
00863               mapHisto_["hDeltaMassOverGenMassVsPt"]->Fill(pt1, diffMass);
00864               mapHisto_["hDeltaMassOverGenMassVsPt"]->Fill(pt2, diffMass);
00865               mapHisto_["hDeltaMassOverGenMassVsEta"]->Fill(eta1, diffMass);
00866               mapHisto_["hDeltaMassOverGenMassVsEta"]->Fill(eta2, diffMass);
00867               // This is used for the covariance comparison
00868               mapHisto_["hMassResolutionVsPtEta"]->Fill(pt1, eta1, diffMass, diffMass);
00869               mapHisto_["hMassResolutionVsPtEta"]->Fill(pt2, eta2, diffMass, diffMass);
00870             }
00871             else {
00872               std::cout << "Error, there is a nan: recoMass = " << recoMass << ", genMass = " << genMass << std::endl;
00873             }
00874           }
00875           // Fill with mass resolution from resolution function
00876           double massRes = MuScleFitUtils::massResolution(recMu1, recMu2, MuScleFitUtils::parResol);
00877           mapHisto_["hFunctionResolMass"]->Fill( recMu1, std::pow(massRes,2), -1 );
00878           mapHisto_["hFunctionResolMass"]->Fill( recMu2, std::pow(massRes,2), +1 );
00879         }
00880 
00881         mapHisto_["hMass_P"]->Fill(bestRecRes.mass(), prob);
00882         if( debug_ > 0 ) std::cout << "mass = " << bestRecRes.mass() << ", prob = " << prob << std::endl;
00883         mapHisto_["hMass_fine_P"]->Fill(bestRecRes.mass(), prob);
00884 
00885         mapHisto_["hMassProbVsRes"]->Fill(bestRecRes, bestRecRes, +1, prob);
00886         mapHisto_["hMassProbVsMu"]->Fill(recMu1, bestRecRes, -1, prob);
00887         mapHisto_["hMassProbVsMu"]->Fill(recMu2, bestRecRes, +1, prob);
00888         mapHisto_["hMassProbVsRes_fine"]->Fill(bestRecRes, bestRecRes, +1, prob);
00889         mapHisto_["hMassProbVsMu_fine"]->Fill(recMu1, bestRecRes, -1, prob);
00890         mapHisto_["hMassProbVsMu_fine"]->Fill(recMu2, bestRecRes, +1, prob);
00891       }
00892     }
00893   } // end if ResFound
00894 
00895   // Fill the pair
00896   // -------------
00897   if (loopCounter>0) {
00898     if (debug_>0) std::cout << "[MuScleFit]: filling the pair" << std::endl;
00899     MuScleFitUtils::SavedPair[iev] = std::make_pair( recMu1, recMu2 );
00900   }
00901 
00902   iev++;
00903   MuScleFitUtils::iev_++;
00904 
00905   // return kContinue;
00906 }
00907 
00908 bool MuScleFit::checkDeltaR(reco::Particle::LorentzVector& genMu, reco::Particle::LorentzVector& recMu){
00909   //first is always mu-, second is always mu+
00910   double deltaR = sqrt(MuScleFitUtils::deltaPhi(recMu.Phi(),genMu.Phi()) * MuScleFitUtils::deltaPhi(recMu.Phi(),genMu.Phi()) +
00911                        ((recMu.Eta()-genMu.Eta()) * (recMu.Eta()-genMu.Eta())));
00912   if(deltaR<0.01)
00913     return true;
00914   else if( debug_ > 0 ) {
00915     std::cout<<"Reco muon "<<recMu<<" with eta "<<recMu.Eta()<<" and phi "<<recMu.Phi()<<std::endl
00916         <<" DOES NOT MATCH with generated muon from resonance: "<<std::endl
00917         <<genMu<<" with eta "<<genMu.Eta()<<" and phi "<<genMu.Phi()<<std::endl;
00918   }
00919   return false;
00920 }
00921 
00922 void MuScleFit::fillComparisonHistograms( const reco::Particle::LorentzVector & genMu, const reco::Particle::LorentzVector & recMu,
00923                                           const std::string & inputName, const int charge )
00924 {
00925   std::string name(inputName + "VSMu");
00926   mapHisto_["hResolPt"+name]->Fill(recMu, (-genMu.Pt()+recMu.Pt())/genMu.Pt(), charge);
00927   mapHisto_["hResolTheta"+name]->Fill(recMu, (-genMu.Theta()+recMu.Theta()), charge);
00928   mapHisto_["hResolCotgTheta"+name]->Fill(recMu,(-cos(genMu.Theta())/sin(genMu.Theta())
00929                                                  +cos(recMu.Theta())/sin(recMu.Theta())), charge);
00930   mapHisto_["hResolEta"+name]->Fill(recMu, (-genMu.Eta()+recMu.Eta()),charge);
00931   mapHisto_["hResolPhi"+name]->Fill(recMu, MuScleFitUtils::deltaPhiNoFabs(recMu.Phi(), genMu.Phi()), charge);
00932 
00933   // Fill only if it was matched to a genMu and this muon is valid
00934   if( (genMu.Pt() != 0) && (recMu.Pt() != 0) ) {
00935     mapHisto_["hPtRecoVsPt"+inputName]->Fill(genMu.Pt(), recMu.Pt());
00936   }
00937 }
00938 
00939 void MuScleFit::applySmearing( reco::Particle::LorentzVector & mu )
00940 {
00941   if( MuScleFitUtils::SmearType>0 ) {
00942     mu = MuScleFitUtils::applySmearing( mu );
00943     if (debug_>0) std::cout << "Muon #" << MuScleFitUtils::goodmuon
00944                        << ": after smearing  Pt = " << mu.Pt() << std::endl;
00945   }
00946 }
00947 
00948 void MuScleFit::applyBias( reco::Particle::LorentzVector & mu, const int charge )
00949 {
00950   if( MuScleFitUtils::BiasType>0 ) {
00951     mu = MuScleFitUtils::applyBias( mu, charge );
00952     if (debug_>0) std::cout << "Muon #" << MuScleFitUtils::goodmuon
00953                        << ": after bias      Pt = " << mu.Pt() << std::endl;
00954   }
00955 }
00956 
00957 // Simple method to check parameters consistency. It aborts the job if the parameters
00958 // are not consistent.
00959 void MuScleFit::checkParameters() {
00960 
00961   // Fits selection dimension check
00962   if( MuScleFitUtils::doResolFit.size() != maxLoopNumber ) {
00963     std::cout << "[MuScleFit-Constructor]: wrong size of resolution fits selector = " << MuScleFitUtils::doResolFit.size() << std::endl;
00964     std::cout << "it must have as many values as the number of loops, which is = " << maxLoopNumber << std::endl;
00965     abort();
00966   }
00967   if( MuScleFitUtils::doScaleFit.size() != maxLoopNumber ) {
00968     std::cout << "[MuScleFit-Constructor]: wrong size of scale fits selector = " << MuScleFitUtils::doScaleFit.size() << std::endl;
00969     std::cout << "it must have as many values as the number of loops, which is = " << maxLoopNumber << std::endl;
00970     abort();
00971   }
00972   if( MuScleFitUtils::doCrossSectionFit.size() != maxLoopNumber ) {
00973     std::cout << "[MuScleFit-Constructor]: wrong size of cross section fits selector = " << MuScleFitUtils::doCrossSectionFit.size() << std::endl;
00974     std::cout << "it must have as many values as the number of loops, which is = " << maxLoopNumber << std::endl;
00975     abort();
00976   }
00977   if( MuScleFitUtils::doBackgroundFit.size() != maxLoopNumber ) {
00978     std::cout << "[MuScleFit-Constructor]: wrong size of background fits selector = " << MuScleFitUtils::doBackgroundFit.size() << std::endl;
00979     std::cout << "it must have as many values as the number of loops, which is = " << maxLoopNumber << std::endl;
00980     abort();
00981   }
00982 
00983   // Bias parameters: dimension check
00984   // --------------------------------
00985   if ((MuScleFitUtils::BiasType==1  && MuScleFitUtils::parBias.size()!=2) || // linear in pt
00986       (MuScleFitUtils::BiasType==2  && MuScleFitUtils::parBias.size()!=2) || // linear in |eta|
00987       (MuScleFitUtils::BiasType==3  && MuScleFitUtils::parBias.size()!=4) || // sinusoidal in phi
00988       (MuScleFitUtils::BiasType==4  && MuScleFitUtils::parBias.size()!=3) || // linear in pt and |eta|
00989       (MuScleFitUtils::BiasType==5  && MuScleFitUtils::parBias.size()!=3) || // linear in pt and sinusoidal in phi
00990       (MuScleFitUtils::BiasType==6  && MuScleFitUtils::parBias.size()!=3) || // linear in |eta| and sinusoidal in phi
00991       (MuScleFitUtils::BiasType==7  && MuScleFitUtils::parBias.size()!=4) || // linear in pt and |eta| and sinusoidal in phi
00992       (MuScleFitUtils::BiasType==8  && MuScleFitUtils::parBias.size()!=4) || // linear in pt and parabolic in |eta|
00993       (MuScleFitUtils::BiasType==9  && MuScleFitUtils::parBias.size()!=2) || // exponential in pt
00994       (MuScleFitUtils::BiasType==10 && MuScleFitUtils::parBias.size()!=3) || // parabolic in pt
00995       (MuScleFitUtils::BiasType==11 && MuScleFitUtils::parBias.size()!=4) || // linear in pt and sin in phi with chg
00996       (MuScleFitUtils::BiasType==12 && MuScleFitUtils::parBias.size()!=6) || // linear in pt and para in plus sin in phi with chg
00997       (MuScleFitUtils::BiasType==13 && MuScleFitUtils::parBias.size()!=8) || // linear in pt and para in plus sin in phi with chg
00998       MuScleFitUtils::BiasType<0 || MuScleFitUtils::BiasType>13) {
00999     std::cout << "[MuScleFit-Constructor]: Wrong bias type or number of parameters: aborting!" << std::endl;
01000     abort();
01001   }
01002   // Smear parameters: dimension check
01003   // ---------------------------------
01004   if ((MuScleFitUtils::SmearType==1 && MuScleFitUtils::parSmear.size()!=3) ||
01005       (MuScleFitUtils::SmearType==2 && MuScleFitUtils::parSmear.size()!=4) ||
01006       (MuScleFitUtils::SmearType==3 && MuScleFitUtils::parSmear.size()!=5) ||
01007       (MuScleFitUtils::SmearType==4 && MuScleFitUtils::parSmear.size()!=6) ||
01008       (MuScleFitUtils::SmearType==5 && MuScleFitUtils::parSmear.size()!=7) ||
01009       (MuScleFitUtils::SmearType==6 && MuScleFitUtils::parSmear.size()!=16) ||
01010       (MuScleFitUtils::SmearType==7 && MuScleFitUtils::parSmear.size()!=0) ||
01011       MuScleFitUtils::SmearType<0 || MuScleFitUtils::SmearType>7) {
01012     std::cout << "[MuScleFit-Constructor]: Wrong smear type or number of parameters: aborting!" << std::endl;
01013     abort();
01014   }
01015   // Protect against bad size of parameters
01016   // --------------------------------------
01017   if (MuScleFitUtils::parResol.size()!=MuScleFitUtils::parResolFix.size() ||
01018       MuScleFitUtils::parResol.size()!=MuScleFitUtils::parResolOrder.size()) {
01019     std::cout << "[MuScleFit-Constructor]: Mismatch in number of parameters for Resol: aborting!" << std::endl;
01020     abort();
01021   }
01022   if (MuScleFitUtils::parScale.size()!=MuScleFitUtils::parScaleFix.size() ||
01023       MuScleFitUtils::parScale.size()!=MuScleFitUtils::parScaleOrder.size()) {
01024     std::cout << "[MuScleFit-Constructor]: Mismatch in number of parameters for Scale: aborting!" << std::endl;
01025     abort();
01026   }
01027   if (MuScleFitUtils::parCrossSection.size()!=MuScleFitUtils::parCrossSectionFix.size() ||
01028       MuScleFitUtils::parCrossSection.size()!=MuScleFitUtils::parCrossSectionOrder.size()) {
01029     std::cout << "[MuScleFit-Constructor]: Mismatch in number of parameters for Bgr: aborting!" << std::endl;
01030     abort();
01031   }
01032   if (MuScleFitUtils::parBgr.size()!=MuScleFitUtils::parBgrFix.size() ||
01033       MuScleFitUtils::parBgr.size()!=MuScleFitUtils::parBgrOrder.size()) {
01034     std::cout << "[MuScleFit-Constructor]: Mismatch in number of parameters for Bgr: aborting!" << std::endl;
01035     abort();
01036   }
01037 
01038   // Protect against an incorrect number of resonances
01039   // -------------------------------------------------
01040   if (MuScleFitUtils::resfind.size()!=6) {
01041     std::cout << "[MuScleFit-Constructor]: resfind must have 6 elements (1 Z, 3 Y, 2 Psi): aborting!" << std::endl;
01042     abort();
01043   }
01044 }
01045 
01046 bool MuScleFit::selGlobalMuon(const pat::Muon* aMuon) {
01047 
01048   reco::TrackRef iTrack = aMuon->innerTrack();
01049   const reco::HitPattern& p = iTrack->hitPattern();
01050 
01051   reco::TrackRef gTrack = aMuon->globalTrack();
01052   const reco::HitPattern& q = gTrack->hitPattern();
01053 
01054   return (//isMuonInAccept(aMuon) &&// no acceptance cuts!
01055           iTrack->found() > 11 &&
01056           gTrack->chi2()/gTrack->ndof() < 20.0 &&
01057           q.numberOfValidMuonHits() > 0 &&
01058           iTrack->chi2()/iTrack->ndof() < 4.0 &&
01059           aMuon->muonID("TrackerMuonArbitrated") &&
01060           aMuon->muonID("TMLastStationAngTight") &&
01061           p.pixelLayersWithMeasurement() > 1 &&
01062           fabs(iTrack->dxy()) < 3.0 &&  //should be done w.r.t. PV!
01063           fabs(iTrack->dz()) < 15.0 );//should be done w.r.t. PV!
01064 }
01065  
01066 
01067 bool MuScleFit::selTrackerMuon(const pat::Muon* aMuon) {
01068   
01069   reco::TrackRef iTrack = aMuon->innerTrack();
01070   const reco::HitPattern& p = iTrack->hitPattern();
01071 
01072     return (//isMuonInAccept(aMuon) // no acceptance cuts!
01073           iTrack->found() > 11 &&
01074           iTrack->chi2()/iTrack->ndof() < 4.0 &&
01075           aMuon->muonID("TrackerMuonArbitrated") &&
01076           aMuon->muonID("TMLastStationAngTight") &&
01077           p.pixelLayersWithMeasurement() > 1 &&
01078           fabs(iTrack->dxy()) < 3.0 && //should be done w.r.t. PV!
01079           fabs(iTrack->dz()) < 15.0 );//should be done w.r.t. PV!
01080  
01081 }