CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/RecoTauTag/RecoTau/plugins/PFTauMVADiscriminator.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    PFTauMVADiscriminator
00004 // Class:      PFTauMVADiscriminator
00005 // 
00013 //
00014 // Original Author:  Evan K. Friis, UC Davis (friis@physics.ucdavis.edu)
00015 //         Created:  Fri Aug 15 11:22:14 PDT 2008
00016 // $Id: PFTauMVADiscriminator.cc,v 1.4 2010/10/19 21:29:13 wmtan Exp $
00017 //
00018 //
00019 
00020 #include "RecoTauTag/RecoTau/interface/TauDiscriminationProducerBase.h"
00021 
00022 // Tau discriminant computation
00023 #include "RecoTauTag/TauTagTools/interface/PFTauDiscriminantManager.h"
00024 #include "RecoTauTag/TauTagTools/interface/Discriminants.h"
00025 #include "RecoTauTag/TauTagTools/interface/DiscriminantList.h"
00026 
00027 // PFTauDecayMode data formats
00028 #include "DataFormats/TauReco/interface/PFTauDecayMode.h"
00029 #include "DataFormats/TauReco/interface/PFTauDecayModeAssociation.h"
00030 
00031 // DB access
00032 #include "CondFormats/PhysicsToolsObjects/interface/MVAComputer.h"
00033 #include "RecoTauTag/TauTagTools/interface/TauMVADBConfiguration.h"
00034 #include "PhysicsTools/MVAComputer/interface/MVAComputerRecord.h"
00035 #include "PhysicsTools/MVAComputer/interface/MVAComputer.h"
00036 #include "PhysicsTools/MVAComputer/interface/MVAComputerCache.h"
00037 
00038 using namespace PFTauDiscriminants;
00039 using namespace reco;
00040 
00041 class PFTauMVADiscriminator : public PFTauDiscriminationProducerBase {
00042    public:
00043       explicit PFTauMVADiscriminator(const edm::ParameterSet&);
00044       ~PFTauMVADiscriminator();
00045 
00046       struct  MVAComputerFromDB {
00047          std::string                                 computerName;
00048          PhysicsTools::MVAComputerCache*        computer;
00049          double                                 userCut;
00050       };
00051 
00052       typedef std::vector<MVAComputerFromDB>    MVAList;
00053       typedef std::map<int, MVAList::iterator> DecayModeToMVAMap;
00054 
00055       void beginEvent(const edm::Event&, const edm::EventSetup&); // called at the beginning of each event
00056       double discriminate(const PFTauRef&);             // called on every tau in input collection
00057 
00058    private:
00059       edm::InputTag                  pfTauDecayModeSrc_;
00060       bool                      remapOutput_;      // TMVA defaults output to (-1, 1).  Option to remap to (0, 1)
00061       bool                      applyCut_;         //Specify whether to output the MVA value, or whether to use 
00062                                                    // the cuts specified in the DecayMode VPSet specified in the cfg file 
00063       DecayModeToMVAMap         computerMap_;      //Maps decay mode to MVA implementation
00064       MVAList                   computers_;
00065       std::string               dbLabel_;
00066       DiscriminantList          myDiscriminants_;  // collection of functions to compute the discriminants
00067       PFTauDiscriminantManager  discriminantManager_;
00068 
00069       edm::Handle<PFTauDecayModeAssociation> pfTauDecayModes; // edm::Handle to PFTauDecayModes for current event
00070 
00071       std::vector<PhysicsTools::Variable::Value>        mvaComputerInput_;
00072 };
00073 
00074 PFTauMVADiscriminator::PFTauMVADiscriminator(const edm::ParameterSet& iConfig):PFTauDiscriminationProducerBase(iConfig)
00075 {
00076    pfTauDecayModeSrc_        = iConfig.getParameter<edm::InputTag>("pfTauDecayModeSrc");
00077    remapOutput_              = iConfig.getParameter<bool>("RemapOutput");
00078    applyCut_                 = iConfig.getParameter<bool>("MakeBinaryDecision");
00079    prediscriminantFailValue_ = iConfig.getParameter<double>("prefailValue"); //defined in base class
00080    dbLabel_                  = iConfig.getParameter<std::string>("dbLabel");
00081 
00082    // build the decaymode->computer map
00083    std::vector<edm::ParameterSet> decayModeMap = iConfig.getParameter<std::vector<edm::ParameterSet> >("computers");
00084    computers_.reserve(decayModeMap.size());
00085    for(std::vector<edm::ParameterSet>::const_iterator iComputer  = decayModeMap.begin(); iComputer != decayModeMap.end(); ++iComputer)
00086    {
00087       MVAComputerFromDB toInsert;
00088       toInsert.computerName = iComputer->getParameter<std::string>("computerName");
00089       toInsert.userCut      = iComputer->getParameter<double>("cut");
00090       toInsert.computer     = new PhysicsTools::MVAComputerCache();
00091       MVAList::iterator computerJustAdded = computers_.insert(computers_.end(), toInsert); //add this computer to the end of the list
00092 
00093       //populate the map
00094       std::vector<int> associatedDecayModes = iComputer->getParameter<std::vector<int> >("decayModeIndices");
00095       for(std::vector<int>::const_iterator iDecayMode  = associatedDecayModes.begin();
00096                                       iDecayMode != associatedDecayModes.end();
00097                                     ++iDecayMode)
00098       {
00099          //map this integer specifying the decay mode to the MVA comptuer we just added to the list
00100          std::pair<DecayModeToMVAMap::iterator, bool> insertResult = computerMap_.insert(std::make_pair(*iDecayMode, computerJustAdded));
00101 
00102          //make sure we aren't double mapping a decay mode
00103          if(insertResult.second == false) { //indicates that the current key (decaymode) has already been entered!
00104             throw cms::Exception("PFTauMVADiscriminator::ctor") << "A tau decay mode: " << *iDecayMode << " has been mapped to two different MVA implementations, "
00105                                                               << insertResult.first->second->computerName << " and " << toInsert.computerName 
00106                                                               << ". Please check the appropriate cfi file." << std::endl;
00107          }
00108       }
00109    }
00110 
00111    for(DiscriminantList::const_iterator aDiscriminant  = myDiscriminants_.begin();
00112                                         aDiscriminant != myDiscriminants_.end();
00113                                       ++aDiscriminant)
00114    {
00115       //load the discriminants into the discriminant manager
00116       discriminantManager_.addDiscriminant(*aDiscriminant);
00117    }
00118    
00119 }
00120 
00121 PFTauMVADiscriminator::~PFTauMVADiscriminator()
00122 {
00123    for(MVAList::iterator iMVAComputer  = computers_.begin(); iMVAComputer != computers_.end(); ++iMVAComputer)
00124    {
00125       delete iMVAComputer->computer;
00126    }
00127 }
00128 
00129 // ------------ method called at the beginning of every event by base class
00130 void PFTauMVADiscriminator::beginEvent(const edm::Event& iEvent, const edm::EventSetup& iSetup)
00131 {
00132    // load the PFTauDecayModes
00133    iEvent.getByLabel(pfTauDecayModeSrc_, pfTauDecayModes);
00134 
00135    // expose the event to the PFTau discriminant quantity computers
00136    discriminantManager_.setEvent(iEvent, 1.0); //event weight = 1 
00137 
00138    // Refresh MVAs
00139    //we do this on each event as the crossing an IOV boundary could change the appropriate record
00140    for(MVAList::iterator iMVAComputer  = computers_.begin();
00141                          iMVAComputer != computers_.end();
00142                        ++iMVAComputer)
00143    {
00144       std::string nameToGet = iMVAComputer->computerName;
00145       iMVAComputer->computer->update<TauMVAFrameworkDBRcd>(dbLabel_.c_str(), iSetup, nameToGet.c_str());
00146    } 
00147 }
00148 
00149 double PFTauMVADiscriminator::discriminate(const PFTauRef& pfTau)
00150 {
00151    double result = prediscriminantFailValue_;
00152 
00153    mvaComputerInput_.clear();
00154    const PFTauDecayMode& theTauDecayMode = (*pfTauDecayModes)[pfTau]; // get PFTauDecayMode associated to this PFTau
00155 
00156 
00157    //get appropriate MVA computer
00158    int decayMode = theTauDecayMode.getDecayMode();
00159    DecayModeToMVAMap::iterator iterToComputer = computerMap_.find(decayMode);
00160 
00161    if(iterToComputer != computerMap_.end()) //if we don't have a MVA mapped to this decay mode, skip it.
00162    {
00163       const PhysicsTools::MVAComputerCache* mvaComputer = iterToComputer->second->computer;
00164       if ( (*mvaComputer) ) 
00165       {
00166          //sets the current tau decay mode as the active object
00167          discriminantManager_.setTau(theTauDecayMode);
00168          //applies associated discriminants (see ctor) and constructs the appropriate MVA framework input
00169          discriminantManager_.buildMVAComputerLink(mvaComputerInput_);
00170          result = (*mvaComputer)->eval(mvaComputerInput_);
00171       } 
00172       else 
00173       {
00174          edm::LogWarning("PFTauMVADiscriminator") << "Warning: got a null pointer to MVA computer in conditions database"
00175             << " for decay mode: " << decayMode << ", expected MVA computer name: " 
00176             << iterToComputer->second->computerName;
00177       }
00178 
00179       if (remapOutput_) // TMVA maps result to [-1, 1].  Remap, if desired, to [0, 1]
00180       {
00181          if      (result >  1) result = 1.;
00182          else if (result < -1) result = 0.;
00183          else { 
00184             result += 1.;
00185             result /= 2.;
00186          }
00187       }
00188       if (applyCut_)
00189       {
00190          //If the user desires a yes or no decision, 
00191          // use the supplied cut to make a decision
00192          if (result > iterToComputer->second->userCut) 
00193             result = 1.0;
00194          else 
00195             result = 0.0;
00196       }
00197    }
00198 
00199    return result;
00200 }
00201 
00202 
00203 //define this as a plug-in
00204 DEFINE_FWK_MODULE(PFTauMVADiscriminator);