CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_7_hltpatch1/src/PhysicsTools/FWLite/examples/secvtxMassTemplates.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // CMS includes
00004 #include "DataFormats/FWLite/interface/Handle.h"
00005 #include "DataFormats/PatCandidates/interface/Jet.h"
00006 #include "DataFormats/PatCandidates/interface/Muon.h"
00007 #include "DataFormats/HepMCCandidate/interface/FlavorHistory.h"
00008 #include "DataFormats/HepMCCandidate/interface/GenParticle.h"
00009 #include "Math/GenVector/PxPyPzM4D.h"
00010 
00011 #include "PhysicsTools/FWLite/interface/EventContainer.h"
00012 #include "PhysicsTools/FWLite/interface/CommandLineParser.h" 
00013 
00014 // Root includes
00015 #include "TROOT.h"
00016 #include "TH2F.h"
00017 
00018 using namespace std;
00019 using optutl::CommandLineParser;
00020 
00021 enum
00022 {
00023    kNormalMode,
00024    kVqqMode,
00025    kLFMode,
00026    kWcMode
00027 };
00028 
00030 // Forward Declarations //
00032 
00033 // This subroutine, written by you (below), uses the command line
00034 // arguments and creates an output tag (if any).  This subroutine must
00035 // exist.
00036 void outputNameTagFunc (string &tag);
00037 
00038 // Book all histograms to be filled this job.  If wanted, you can skip
00039 // this subroutine and book all histograms in the main subroutine.
00040 void bookHistograms (fwlite::EventContainer &eventCont);
00041 
00042 // Calculate the name that should be used for this event based on the
00043 // mode, the HF word, and (if necessary), whether or not it's a W or
00044 // Z.  Returns false if the event should not be processed.
00045 bool calcSampleName (fwlite::EventContainer &eventCont, string &sampleName);
00046 
00048 // ///////////////////// //
00049 // // Main Subroutine // //
00050 // ///////////////////// //
00052 
00053 int main (int argc, char* argv[]) 
00054 {
00056    // ////////////////////////// //
00057    // // Command Line Options // //
00058    // ////////////////////////// //
00060 
00061    // Tell people what this analysis code does and setup default options.
00062    CommandLineParser parser ("Creates SecVtx Mass templates");
00063 
00065    // Add any command line options you would like here //
00067    parser.addOption ("mode",         CommandLineParser::kInteger, 
00068                      "Normal(0), VQQ(1), LF(2), Wc(3)", 
00069                      0);   
00070    parser.addOption ("sampleName",   CommandLineParser::kString, 
00071                      "Sample name (e.g., top, Wqq, etc.)");   
00072 
00074    parser.stringValue ("outputFile") = "jetPt"; // .root added automatically
00075 
00076    // Parse the command line arguments
00077    parser.parseArguments (argc, argv);
00078 
00080    // //////////////////////////// //
00081    // // Create Event Container // //
00082    // //////////////////////////// //
00084 
00085    // This object 'eventCont' is used both to get all information from the
00086    // eventCont as well as to store histograms, etc.
00087    // Parse the command line arguments
00088    parser.parseArguments (argc, argv);
00089 
00091    // //////////////////////////// //
00092    // // Create Event Container // //
00093    // //////////////////////////// //
00095 
00096    fwlite::EventContainer eventCont (parser);
00097 
00099    // ////////////////////////////////// //
00100    // //         Begin Run            // //
00101    // // (e.g., book histograms, etc) // //
00102    // ////////////////////////////////// //
00104 
00105    // Setup a style
00106    gROOT->SetStyle ("Plain");
00107 
00108    // Book those histograms!
00109    bookHistograms (eventCont);
00110 
00112    // //////////////// //
00113    // // Event Loop // //
00114    // //////////////// //
00116 
00117    for (eventCont.toBegin(); !eventCont.atEnd(); ++eventCont) 
00118    {
00120       // Take What We Need From Event //
00122       fwlite::Handle< vector< pat::Jet > > jetCollection;
00123       jetCollection.getByLabel (eventCont, "selectedLayer1Jets");
00124       assert ( jetCollection.isValid() );
00125                                                 
00126       fwlite::Handle< vector< pat::Muon > > goodMuonCollection;
00127       goodMuonCollection.getByLabel (eventCont, "goodLeptons");
00128       assert ( goodMuonCollection.isValid() );
00129                         
00130       // If we don't have any good leptons, don't bother
00131       if (! goodMuonCollection->size() )
00132       {
00133          continue;
00134       }
00135 
00136       // get the sample name for this event
00137       string sampleName;
00138       if ( ! calcSampleName (eventCont, sampleName) )
00139       {
00140          // We don't want this one.
00141          continue;
00142       }
00143 
00145       // Tagged Jets and Flavor Separator //
00147       int numBottom = 0, numCharm = 0, numLight = 0;
00148       int numTags = 0;
00149       double sumVertexMass = 0.;
00150       // Loop over the jets and find out which are tagged
00151       const vector< pat::Jet >::const_iterator kJetEnd = jetCollection->end();
00152       for (vector< pat::Jet >::const_iterator jetIter = jetCollection->begin(); 
00153            kJetEnd != jetIter; 
00154            ++jetIter) 
00155       {
00156          // Is this jet tagged and does it have a good secondary vertex
00157          if( jetIter->bDiscriminator("simpleSecondaryVertexBJetTags") < 2.05 )
00158          {
00159             // This jet isn't tagged
00160             continue;
00161          }
00162          reco::SecondaryVertexTagInfo const * svTagInfos 
00163             = jetIter->tagInfoSecondaryVertex("secondaryVertex");
00164          if ( svTagInfos->nVertices() <= 0 ) 
00165          {
00166             // Given that we are using simple secondary vertex
00167             // tagging, I don't think this should ever happen.
00168             // Maybe we should put a counter here just to check.
00169             continue;
00170          } // if we have no secondary verticies
00171          
00172          // count it
00173          ++numTags;
00174 
00175          // What is the flavor of this jet
00176          int jetFlavor = std::abs( jetIter->partonFlavour() );
00177          if (5 == jetFlavor)
00178          {
00179             ++numBottom;
00180          } // if bottom 
00181          else if (4 == jetFlavor)
00182          {
00183             ++numCharm;
00184          } // if charm
00185          else
00186          {
00187             ++numLight;
00188          } // if light flavor
00189 
00191          // Calculate SecVtx Mass //
00193          ROOT::Math::LorentzVector< ROOT::Math::PxPyPzM4D<double> > sumVec;
00194          reco::CompositeCandidate vertexCand;
00195          reco::Vertex::trackRef_iterator 
00196             kEndTracks = svTagInfos->secondaryVertex(0).tracks_end();
00197          for (reco::Vertex::trackRef_iterator trackIter = 
00198                  svTagInfos->secondaryVertex(0).tracks_begin(); 
00199               trackIter != kEndTracks; 
00200               ++trackIter ) 
00201          {
00202             const double kPionMass = 0.13957018;
00203             ROOT::Math::LorentzVector< ROOT::Math::PxPyPzM4D<double> > vec;
00204             vec.SetPx( (*trackIter)->px() );
00205             vec.SetPy( (*trackIter)->py() );
00206             vec.SetPz( (*trackIter)->pz() );
00207             vec.SetM (kPionMass);
00208             sumVec += vec;
00209          } // for trackIter
00210          sumVertexMass += sumVec.M();
00211          if (2 == numTags)
00212          {
00213             // We've got enough.  Stop.
00214             break;
00215          } // if we have enough tags
00216       } // for jet
00217 
00219       // General Accounting //
00221       int numJets = std::min( (int) jetCollection->size(), 5 );
00222       eventCont.hist( sampleName + "_jettag")->Fill (numJets, numTags);
00223 
00224       // If we don't have any tags, don't bother going on
00225       if ( ! numTags)
00226       {
00227          continue;
00228       }
00229 
00231       // Calculate average SecVtx mass and //
00232       // fill appropriate histograms.      //
00234       sumVertexMass /= numTags;
00235       string whichtag = "";
00236       if (1 == numTags)
00237       {
00238          // single tag
00239          if      (numBottom)              whichtag = "_b";
00240          else if (numCharm)               whichtag = "_c";
00241          else if (numLight)               whichtag = "_q";
00242          else                             whichtag = "_X";
00243       } else {
00244          // double tags
00245          if      (2 == numBottom)         whichtag = "_bb";
00246          else if (2 == numCharm)          whichtag = "_cc";
00247          else if (2 == numLight)          whichtag = "_qq";
00248          else if (numBottom && numCharm)  whichtag = "_bc";
00249          else if (numBottom && numLight)  whichtag = "_bq";
00250          else if (numCharm  && numLight)  whichtag = "_bq";
00251          else                             whichtag = "_XX";
00252       } // if two tags
00253       string massName = sampleName 
00254          + Form("_secvtxMass_%dj_%dt", numJets, numTags);
00255       eventCont.hist(massName)->Fill (sumVertexMass);
00256       eventCont.hist(massName + whichtag)->Fill (sumVertexMass);
00257    } // for eventCont
00258       
00260    // ////////////////// //
00261    // // Clean Up Job // //
00262    // ////////////////// //
00264 
00265    // Histograms will be automatically written to the root file
00266    // specificed by command line options.
00267 
00268    // All done!  Bye bye.
00269    return 0;
00270 }
00271 
00272 
00278 
00279 
00280 void outputNameTagFunc (string &tag)
00281 {
00282    // If you do not want to give you output filename any "tag" based
00283    // on the command line options, simply do nothing here.  This
00284    // function is designed to be called by fwlite::EventContainer constructor.
00285 
00286    // if ( boolValue ("someCondition") )
00287    // { 
00288    //    tag += "_someCond";
00289    // }
00290 }
00291 
00292 
00293 void bookHistograms (fwlite::EventContainer &eventCont)
00294 {
00296    // First, come up with all possible base   //
00297    // names (E.g., Wbb, Wb2, etc.).           //
00299    CommandLineParser &parser = eventCont.parser();
00300    CommandLineParser::SVec baseNameVec;
00301    CommandLineParser::SVec beginningVec, endingVec;
00302    switch ( parser.integerValue ("mode") )
00303    {
00304       case kVqqMode:
00305          // We want Wbb, Wb2, .., Zbb, ..  In this case, we completely
00306          // ignore the sampleName that was passed in.
00307          // Starts with
00308          beginningVec.push_back ("X");
00309          beginningVec.push_back ("W");
00310          beginningVec.push_back ("Z");
00311          // Ends with
00312          endingVec.push_back( "bb" );
00313          endingVec.push_back( "b2" );
00314          endingVec.push_back( "cc" );
00315          endingVec.push_back( "c2" );
00316          for (CommandLineParser::SVecConstIter outerIter = beginningVec.begin();
00317               beginningVec.end() != outerIter;
00318               ++outerIter)
00319          {
00320             for (CommandLineParser::SVecConstIter innerIter = endingVec.begin();
00321                  endingVec.end() != innerIter;
00322                  ++innerIter)
00323             {
00324                baseNameVec.push_back( *outerIter + *innerIter);
00325             } // for innerIter
00326          } // for outerIter
00327          break;
00328       case kLFMode:
00329          // just like the default case, except that we do have some
00330          // heavy flavor pieces here, too.
00331          baseNameVec.push_back(parser.stringValue ("sampleName") + "b3");
00332          baseNameVec.push_back(parser.stringValue ("sampleName") + "c3");
00333          // no break because to add just the name as well
00334       default:
00335          // We just want to use the sample name as it was given to us.
00336          baseNameVec.push_back(parser.stringValue ("sampleName"));
00337    } // for switch
00338 
00340    // Now the different tagging endings. //
00342    CommandLineParser::SVec singleTagEndingVec, doubleTagEndingVec;
00343    singleTagEndingVec.push_back ("_b");
00344    singleTagEndingVec.push_back ("_c");
00345    singleTagEndingVec.push_back ("_q");
00346    doubleTagEndingVec.push_back ("_bb");
00347    doubleTagEndingVec.push_back ("_cc");
00348    doubleTagEndingVec.push_back ("_qq");
00349    doubleTagEndingVec.push_back ("_bc");
00350    doubleTagEndingVec.push_back ("_bq");
00351    doubleTagEndingVec.push_back ("_cq");
00352 
00354    // Finally, let's put it all together. //
00356    for (CommandLineParser::SVecConstIter baseIter = baseNameVec.begin();
00357         baseNameVec.end() != baseIter;
00358         ++baseIter)
00359    {
00361       // For each flavor, one jet/tag counting histogram. //
00363       TString histName = *baseIter + "_jettag";
00364       eventCont.add( new TH2F( histName, histName, 
00365                                6, -0.5, 5.5,
00366                                3, -0.5, 2.5) );
00367       for (int jet = 1; jet <= 5; ++jet)
00368       {
00369          for (int tag = 1; tag <= 2; ++tag)
00370          {
00372             // For each jet/tag, a single secvtx mass //
00374             if (tag > jet) continue;
00375             histName = *baseIter + Form ("_secvtxMass_%dj_%dt", jet, tag);
00376             eventCont.add( new TH1F( histName, histName, 40, 0, 10) );
00377             CommandLineParser::SVec *vecPtr = &singleTagEndingVec;
00378             if (2 == tag)
00379             {
00380                vecPtr = &doubleTagEndingVec;
00381             } // double tag
00382             for (CommandLineParser::SVecConstIter tagIter = vecPtr->begin();
00383                  vecPtr->end() != tagIter;
00384                  ++tagIter)
00385             {
00387                // And different secvtx mass for each tag ending. //
00389                histName = *baseIter + Form ("_secvtxMass_%dj_%dt", jet, tag)
00390                   + *tagIter;
00391                eventCont.add( new TH1F( histName, histName, 40, 0, 10) );
00392             } // for tagIter
00393          } // for tag
00394       } // for jet
00395    } // for baseIter
00396 }
00397                                         
00398 
00399 bool calcSampleName (fwlite::EventContainer &eventCont, string &sampleName)
00400 {
00401    // calculate sample name
00402    CommandLineParser &parser = eventCont.parser();
00403    sampleName = parser.stringValue  ("sampleName");
00404    int mode   = parser.integerValue ("mode");
00405 
00407    // Normal Mode //
00409    if (kNormalMode == mode)
00410    {
00411       // all we want is the sample name, so in this case we're done.
00412       return true;
00413    }
00414    // Get the heavy flavor category
00415    fwlite::Handle< unsigned int > heavyFlavorCategory;
00416    heavyFlavorCategory.getByLabel (eventCont, "flavorHistoryFilter");
00417    assert ( heavyFlavorCategory.isValid() );
00418    int HFcat = (*heavyFlavorCategory);
00419 
00421    // Light Flavor Mode //
00423    if (kLFMode == mode)
00424    {
00425       // Wqq
00426       if (5 == HFcat)
00427       {
00428          sampleName += "b3";
00429       } else if (6 == HFcat)
00430       {
00431          sampleName += "c3";
00432       } else if (11 != HFcat)
00433       {
00434          // skip this event
00435          return false;
00436       } // else if ! 11
00437       return true;
00438    }
00439 
00441    // Wc Mode //
00443    if (kWcMode == mode)
00444    {
00445       // Wc
00446       if (4 != HFcat)
00447       {
00448          // skip this event
00449          return false;
00450       } // if not Wc
00451       return true;
00452    } // else if Wc
00453 
00455    // Vqq Mode //
00457    // MadGraph (at least as CMS has implemented it) has this _lovely_
00458    // feature that if the W or Z is far enough off-shell, it erases
00459    // the W or Z from the event record.  This means that in some
00460    // number of cases, we won't be able to tell whether this is a W or
00461    // Z event by looking for a W or Z in the GenParticle collection.
00462    // (We'll eventually have to be more clever).
00463    sampleName = "X";
00464    fwlite::Handle< vector< reco::GenParticle > > genParticleCollection;
00465    genParticleCollection.getByLabel (eventCont, "genParticles");
00466    assert ( genParticleCollection.isValid() );
00467    // We don't know if it is a W, a Z, or neither
00468    // Iterate over genParticles
00469    const vector< reco::GenParticle>::const_iterator 
00470       kGenPartEnd = genParticleCollection->end();
00471    for (vector< reco::GenParticle>::const_iterator gpIter =
00472            genParticleCollection->begin(); 
00473         gpIter != kGenPartEnd; ++gpIter ) 
00474    {
00475       if (gpIter->status() == 3 && std::abs(gpIter->pdgId()) == 23)
00476       {
00477          sampleName = "Z";
00478          break;
00479       }
00480       if (gpIter->status() == 3 && std::abs(gpIter->pdgId()) == 24)
00481       {
00482          sampleName = "W";
00483          break;
00484       }
00485    } // for  gpIter
00486    switch (HFcat)
00487    {
00488       // from:
00489       // https://twiki.cern.ch/twiki/bin/viewauth/CMS/SWGuideFlavorHistory
00490       //  1. W+bb with >= 2 jets from the ME (dr > 0.5)
00491       //  2. W+b or W+bb with 1 jet from the ME
00492       //  3. W+cc from the ME (dr > 0.5)
00493       //  4. W+c or W+cc with 1 jet from the ME
00494       //  5. W+bb with 1 jet from the parton shower (dr == 0.0)
00495       //  6. W+cc with 1 jet from the parton shower (dr == 0.0)
00496       //  7. W+bb with >= 2 partons but 1 jet from the ME (dr == 0.0)
00497       //  8. W+cc with >= 2 partons but 1 jet from the ME (dr == 0.0)
00498       //  9. W+bb with >= 2 partons but 2 jets from the PS (dr > 0.5)
00499       // 10. W+cc with >= 2 partons but 2 jets from the PS (dr > 0.5)
00500       // 11. Veto of all the previous (W+ light jets)
00501       case 1:
00502          sampleName += "bb";
00503          break;
00504       case 2:
00505          // Sometimes this is referred to as 'b' (e.g., 'Wb'), but I
00506          // am using the suffix '2' to keep this case clear for when
00507          // we have charm (see below).
00508          sampleName += "b2";
00509          break; 
00510       case 3:
00511          sampleName += "cc";
00512          break;
00513       case 4:
00514          // We want to keep this case clear from real W + single charm
00515          // produced (as opposed to two charm quarks produced and one
00516          // goes down the beampipe), so we use 'c2' instead of 'c'.
00517          sampleName += "c2";
00518          break;
00519       default:
00520          // we don't want the rest of the cases.  Return an empty
00521          // string so we know.
00522          return false;
00523    } // switch HFcat
00524    return true;
00525 }