is created and used inside run.cxx. It calls a predefined function in a separated JO file for a specific study. Default is "ttHDefaultAna". Some of you have already their JO with their name. For this tutorial I created analysisName=CPPMTuTo which calls the function runTuto in util/CPPMTuTo.h. The code to do this rudimentary:
#include "CPPMTuTo.h"
...
if("CPPMTuTo"==config.analysisName){
runTuto(theapp, config, runOption);
}
So lets run with CPPMTuTo:
run input.txt output.root maxEvents=10000 analysisName=CPPMTuTo
Now the output file is empty (still have the same structure but no algos but CutFlowHistoFiller which is added by default).
Lets now add our sequence and add an algo to it. We will do all of this in util/CPPMTuTo.h. Open util/CPPMTuTo.h (with emacs, vi people are not allowed in this tutorial :-p, for the others well we can ignore you ) and add:
(note that algo names should be unique so you have to follow a naming convention.
std::string localName = "cppmTuto";
///create our sequence and add it to application manager.
AlgSequence* basic_seq=new AlgSequence("AlgSequence_"+localName);
theapp.addAlgo(basic_seq);
TuToAlgo* tutoalgo = new TuToAlgo("TuToAlgo_"+localName);
tutoalgo->m_jetcontainername="selected_jets";
basic_seq->addAlgo(tutoalgo);
Now lets create a new algo to the sequence. First we have to create it. Lets call it TuToAlgo. So you have to create TuToAlgo.h class in TTHbbNtupleAnalysis and TuToAlgo.cxx in Root.
TuToAlgo.h will contain (have to inherit from AlgoBase):
#ifndef TuToAlgo_HH
#define TuToAlgo_HH
#include "TTHbbNtupleAnalysis/AlgoBase.h"
class TuToAlgo : public AlgoBase{
public:
explicit TuToAlgo(std::string);
virtual ~TuToAlgo();
virtual bool initialize();
virtual bool execute();
virtual bool finalize();
std::string m_jetcontainername;
private:
double m_eventWeight;
TH1* h_jet_pt;
};
#endif
And TuToAlgo.cxx contains:
#include "TTHbbNtupleAnalysis/TuToAlgo.h"
TuToAlgo::TuToAlgo(std::string name) : AlgoBase(name){
m_jetcontainername="";
}
TuToAlgo::~TuToAlgo(){
////
}
bool TuToAlgo::initialize(){
std::cout << m_name << " initialize " << endl;
m_histoSvc->registerHisto(h_jet_pt,"h_jet_pt",60,25,250);
m_histoSvc->sumw2();
m_cuts->setEventWeight(m_eventWeight);
return true;
}
bool TuToAlgo::execute(){
m_cuts->ocount("in execute "+m_name,0);
MetaData *meta = m_dataStore->getMetaData();
if(!meta){
std::cout << "WARNING " << m_name << " meta data not found " << std::endl;
return false;
}
WeightData *weightData = m_dataStore->getWeightData();
if(!weightData){
std::cout << "WARNING " << m_name << " weight data not found " << std::endl;
return false;
}
m_eventWeight = weightData->getEventWeight("lumi*weight_mc"); ///default "lumi*weight_mc*weight_leptonSF" set in run.cxx, will make default configurable from config.txt
JetContainer* jets = m_dataStore->getJetContainer(m_jetcontainername);
if(!jets){
std::cout << "WARNING " << m_name << " JetContainer " << m_jetcontainername << " not found " << std::endl;
return false;
}
for(auto jet: *jets){
h_jet_pt->Fill(jet->Pt()/1000., m_eventWeight);
}
return true;
}
bool TuToAlgo::finalize(){
std::cout << m_name << " finalize " << endl;
return true;
}
add in utils/run.cxx at the beginning with all other algorithm includes:
#include "TTHbbNtupleAnalysis/TuToAlgo.h"
Now compile go to the run directory that you created and run the code again. You should have your histo in the output file. Browse the output to find it. Notice that it is under a directory with your algo name.
adding histos in different regions
Now lets add several histos to the same algo with different region cuts. First we have to make the algo inherit from RegionInterface.
Add to TuToAlgo.h:
#include "TTHbbMVAInterfaces/RegionInterface.h"
#include "MVAVariables/JetOrderingTool.h"
and then add "public RegionInterface," to the class definition.
Lets also add JetOrderingTool m_jetOrderingTool; as private member of the class and std::string m_eventHolderKey; as public member (initialize it to ="" in the constructor in .cxx).
Also add an array of histos as private member of the class:
TH1* h_jetpt1_pt[20]; /// max allowed regions is 20
Then in TuToAlgo.cxx:
Add "RegionInterface()," to the constructor.
Before "m_histoSvc->sumw2();" add the following to the Initialize function:
for(auto r : m_regions){
m_histoSvc->registerHisto(h_jetpt1_pt[r.index],"h_jetpt1_pt_"+r.name,60,25,300);
}
and in the execute function (before the return true of course):
RecoEvent* eventvar = m_dataStore->getRecoEvent(m_eventHolderKey);
if(!eventvar){
std::cout << "WARNING " << m_name << " RecoEvent " << m_eventHolderKey << " not found " << std::endl;
return false;
}
///.....
m_jetOrderingTool.sortPt(*jets);
vector<int> regions;
getRegions(regions, eventvar->nJets, eventvar->nBJets, eventvar->leptonType, eventvar);
for(auto region : regions){
if(jets->size()>0)h_jetpt1_pt[region]->Fill((*jets)[0]->p4().Pt()/1000.,m_eventWeight);
}
The regions will be added in the JO. If no regions are added no histos will be created. Up to 20 regions can be added since we created an histo array of size 20 (you can make more if you want more histos, but you have to look at them all!!).
There is few ways to add regions in the JO. But we need first to create an event holder in the DataStore that will contain many variables that we can cut on. Here how to do it in util/CPPMTuTo.h (before creating TuToAlgo):
std::string localEventName = "cppmEvent"; /// the name of the event in the store
std::string defaultBtagID = "isbtagged_85"; /// the default btag cut (e.g. nBTags in the event will be @85%,nBTags_85, nBTags_77 decorations ... are also available).
//// create an event holder (TTHbb::RecoEvent class) that will hold all event based variables including choosed reco combinations
EventHolderCreator* evtHolder = new EventHolderCreator("EventHolderCreator_"+localName);
evtHolder->m_inputJets = "selected_jets";
evtHolder->m_inputLeptons = "selected_leptons";
evtHolder->m_inputNeutrinos = "basic_neutrinos";
evtHolder->m_eventHolderKey=localEventName;
evtHolder->m_btagIdName=defaultBtagID;
basic_seq->addAlgo(evtHolder);
/// or use prepareEventHolder(basic_seq, localEventName, defaultBtagID); /// defined in util/JobOptions/EventHolderHelperFunc.h
/// this will add few global variable to the event holder, needed to cut on later (like nBTags_77)
addGlobalVars(basic_seq, localEventName);
addObjectVars(basic_seq, localEventName);
addMVAVars(basic_seq, localEventName, config); /// do not forget to uncomment config in the funtion declaration
Now lets add regions to the algo. There a couple of ways to do it. We can create the region and add it explicitly like this:
///configure region with cuts. Can use decoration into the EventHolder or members like nJets and nBjets (@ default cut that the event holder was created with)
RegionInterface::RegionDefinition r_6jupr;
r_6jupr.name="6jUPR";
r_6jupr.intLowerCut("nBTags_77",4);
r_6jupr.intUpperCut("nBTags_77",10000);
r_6jupr.nJetsMin=6;
r_6jupr.nJetsMax=10000;
RegionInterface::RegionDefinition r_6jsig = getRegion("6jsig", "SemilepRegions_signalRegions", 601);
tutoalgo->addRegion(r_6jupr);
tutoalgo->addRegion(r_6jsig);
tutoalgo->addRegion("6ji3be",6,10000,3,3,0); /// will create region with name, njetsmin, njetsmax, nbjetsmin(@default), nbjetsmax(@default), lepton flavor (0 for no cuts).
tutoalgo->m_eventHolderKey=localEventName;
and now compile and run and see what you get.
-- GeorgesAad - 2017-04-23