SWGuidePATSelectors31x

Object selection in physics analysis is important to structure correctly. The PAT has a great deal of tools available, as well as string-parsed object selectors for single objects. However this can be limited if the user wants to study the cuts being applied. Furthermore, it is difficult to apply these tools in FWLite.

This page refers to using Selectors in the 3.1.4 release. For the 3.3.1 version (now recommended), please see SWGuidePATSelectors.

Selector

The Selector interface is provided to fill this gap. The Selector interface can be used in the full framework, or in FWLite.

The base class is found here with an interface shown in this snippet:

template<class T>
class Selector : public std::binary_function<T, std::strbitset, bool>

The Selector class template is an implementation of the std::binary_function, with arguments of T (the class being operated on), std::strbitset, a string-indexed bitset with source code here, and returns a bool based on whether the object passed the selection.

This interface makes use of the std::strbitset implemented for CMSSW. It performs identically to an ordinary std::bitvector except that the only interface to the information is via std::string keys. Thus, the user can access cuts and values by name rather than by index (which is inherently dangerous and difficult to synchronize).

The Selector class template provides an API as follows:

  • "Declare" the selection in a registry (via the push_back method).
    • This can include selection criteria of doubles, ints, or bools.
    • These selection criteria can also be accessed subsequently via string-index.
  • "Select" the object via an overloaded operator() method.
    • This also returns a strbitset with the bits for each cut set, so the user can see what passed and what failed.
  • "Print" the selection criteria to give the user information about what passed and what failed.

Turning cuts on and off

In order to turn the cuts on and off, the calls are:

  • Turn the cut on:
    set("CutName", true);

  • Turn the cut off:
    set("CutName", false);

This will "auto-pass" events based on this criterion.

Selector<pat::Muon> Example

For instance, a concrete implementation of this to select =pat::Muon='s based on the Summer 08 V+Jets group selection here is included in PhysicsTools/PatUtils. The source is included here, and the relevant snippets are shown here:

  • Register the selection criteria and turn all the cuts "on":

MuonVPlusJetsIDSelectionFunctor( Version_t version ) :
  version_(version)
  {
    push_back("Chi2",     10.0);
    push_back("D0",        0.2);
    push_back("NHits",      11);
    push_back("ECalIso",   6.0);
    push_back("HCalIso",   4.0);
    push_back("RelIso",    0.1);

    set("Chi2");
    set("D0");
    set("NHits");
    set("ECalVeto");
    set("HCalVeto");
    set("RelIso");
  }

  • Define the selection:

// Allow for multiple definitions of the cuts. 
  bool operator()( const pat::Muon & muon, std::strbitset & ret ) 
  { 

    if ( version_ == SUMMER08 ) return summer08Cuts( muon, ret );
    else {
      return false;
    }
  }

  // cuts based on craft 08 analysis. 
  bool summer08Cuts( const pat::Muon & muon, std::strbitset & ret)
  {
    double norm_chi2 = muon.normChi2();
    double corr_d0 = muon.dB();
    int nhits = static_cast<int>( muon.numberOfValidHits() );
    
    double ecalVeto = muon.isolationR03().emVetoEt;
    double hcalVeto = muon.isolationR03().hadVetoEt;
	
    double hcalIso = muon.hcalIso();
    double ecalIso = muon.ecalIso();
    double trkIso  = muon.trackIso();
    double pt      = muon.pt() ;

    double relIso = (ecalIso + hcalIso + trkIso) / pt;

    if ( norm_chi2     <  cut("Chi2",   double()) || ignoreCut("Chi2")    ) passCut(ret, "Chi2"   );
    if ( fabs(corr_d0) <  cut("D0",     double()) || ignoreCut("D0")      ) passCut(ret, "D0"     );
    if ( nhits         >= cut("NHits",  int()   ) || ignoreCut("NHits")   ) passCut(ret, "NHits"  );
    if ( hcalVeto      <  cut("HCalVeto",double())|| ignoreCut("HCalVeto")) passCut(ret, "HCalVeto");
    if ( ecalVeto      <  cut("ECalVeto",double())|| ignoreCut("ECalVeto")) passCut(ret, "ECalVeto");
    if ( relIso        <  cut("RelIso", double()) || ignoreCut("RelIso")  ) passCut(ret, "RelIso" );

    return (bool)ret;
  }

  • An example snippet of how to use this is:

MuonVPlusJetsIDSelectionFunctor muonIdTight( MuonVPlusJetsIDSelectionFunctor::SUMMER08 );

// ...
// other initialization for your FWLite script here
// ...



  for ( std::vector<pat::Muon>::const_iterator muonBegin = allMuons->begin(),
	  muonEnd = allMuons->end(), imuon = muonBegin;
	imuon != muonEnd; ++imuon ) {
    std::strbitset iret = muonIdTight.getBitTemplate();
    if ( imuon->pt() > muPtMin_ && muonIdTight(*imuon, iret) ) {
      selectedMuons_.push_back( *imuon );
    }
  }

See here for a guide to FWLite, and see here for examples of FWLite macros.

There is also a nice prescription for creating standalone executables in FWLite using scram described here.

Selector<pat::PatSummaryEvent>

There is also the possibility to create event selectors from the Selector interface. In software releases &gt 3.3.0, this can work on the entire event because there was the creation of a common base class for edm::Event and fwlite::Event. However in 3.1.4 this is not possible, so a proxy is taken for the time being. The code is here.

This very trivially implements the Selector to a concrete implementation. An example of using this functionality for the TOPANA Synchronization exercise is shown here.

The same API is used for the event selector as for the object selectors, so the same sequence applies.

  • Register the selection criteria:

WPlusJetsTopAnaXMuonEventSelector::WPlusJetsTopAnaXMuonEventSelector( 
    boost::shared_ptr<MuonVPlusJetsIDSelectionFunctor> & muonIdTight,
    boost::shared_ptr<ElectronVPlusJetsIDSelectionFunctor> & electronIdTight,
    boost::shared_ptr<JetIDSelectionFunctor> & jetIdTight,
    boost::shared_ptr<MuonVPlusJetsIDSelectionFunctor> & muonIdLoose,
    boost::shared_ptr<ElectronVPlusJetsIDSelectionFunctor> & electronIdLoose,
    boost::shared_ptr<JetIDSelectionFunctor> & jetIdLoose,
    int minJets,
    bool muPlusJets,
    bool ePlusJets,
    double muPtMin       , double muEtaMax,
    double elePtMin      , double eleEtaMax,
    double muPtMinLoose  , double muEtaMaxLoose,
    double elePtMinLoose , double eleEtaMaxLoose,
    double jetPtMin      , double jetEtaMax
    ) :
  muonIdTight_(muonIdTight),
  electronIdTight_(electronIdTight),
  jetIdTight_(jetIdTight),
  muonIdLoose_(muonIdLoose),
  electronIdLoose_(electronIdLoose),
  jetIdLoose_(jetIdLoose),
  minJets_(minJets),
  muPlusJets_(muPlusJets),
  ePlusJets_(ePlusJets),
  muPtMin_(muPtMin), muEtaMax_(muEtaMax),
  elePtMin_(elePtMin), eleEtaMax_(eleEtaMax),
  muPtMinLoose_(muPtMinLoose), muEtaMaxLoose_(muEtaMaxLoose),
  elePtMinLoose_(elePtMinLoose), eleEtaMaxLoose_(eleEtaMaxLoose),
  jetPtMin_(jetPtMin), jetEtaMax_(jetEtaMax)
{
  // make the bitset
  push_back( "Inclusive"         );
  push_back( "Trigger + 1 GlMu"  );
  push_back( "1 Tight Mu"        );
  push_back( ">= 4 Jets"         , minJets_ );
  push_back( "No Loose Muons"    );
  push_back( "No Loose Electrons");

  // all on by default
  set( "Inclusive"         );
  set( "Trigger + 1 GlMu"  );
  set( "1 Tight Mu"        );
  set( ">= 4 Jets"         );
  set( "No Loose Muons"    );
  set( "No Loose Electrons");

}

  • Define the selection:

pat::TriggerEvent const * trig = t.triggerEvent;

  bool passTrig = false;

  if ( trig->wasRun() && trig->wasAccept() ) {

    pat::TriggerPath const * muPath = trig->path("HLT_Mu9");

    pat::TriggerPath const * elePath = trig->path("HLT_Ele15_LW_L1R");

    if ( muPlusJets_ && muPath != 0 && muPath->wasAccept() ) {
      passTrig = true;    
    }

    if ( ePlusJets_ && elePath != 0 && elePath->wasAccept() ) {
      passTrig = true;
    }

    if ( ignoreCut("Trigger + 1 GlMu") || 
	 (passTrig && nGlobalMuons >= 1) ) {
      passCut(ret, "Trigger + 1 GlMu");

      if ( ignoreCut("1 Tight Mu") || 
	   ( selectedMuons_.size()  == 1 ) ){
	passCut( ret, "1 Tight Mu");

	if ( ignoreCut(">= 4 Jets") ||
	     static_cast<int>(selectedJets_.size()) >=  this->cut(">= 4 Jets", int()) ){
	  passCut(ret,">= 4 Jets");

	  
	  if ( ignoreCut("No Loose Muons") ||
	       looseMuons_.size() == 0 ){
	    passCut(ret,"No Loose Muons");
	    

	    
	    if ( ignoreCut("No Loose Electrons") ||
		 looseElectrons_.size() + selectedElectrons_.size() == 0 ){
	      passCut(ret,"No Loose Electrons");
	      
	    } // end if no loose electrons
	    
	  } // end if no loose muons
      
	} // end if 1 tight jet 
	
      } // end if == 1 lepton
      
    } // end if trigger and 1 global lepton
    
  } // end if event triggered
  
  return (bool)ret;


  • An example snippet of how to use this
is shown here.

-- SalvatoreRoccoRappoccio - 2009-09-30

Edit | Attach | Watch | Print version | History: r6 < r5 < r4 < r3 < r2 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r6 - 2009-12-10 - KatiLassilaPerini
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    CMSPublic All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2020 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback