DAS  3.0
Das Analysis System
DAS::TPS Namespace Reference

Classes

struct  has_p4
 
struct  has_p4< T, std::void_t< decltype(std::declval< T >().p4.Eta())> >
 
struct  Hist
 
struct  MultiJets
 

Enumerations

enum  RemovalStrategy { DeltaR, AntikT, None }
 

Functions

void CheckConsistency (DT::MetaInfo &metainfo1, TTree *tIn1, DT::MetaInfo &metainfo2, TTree *tIn2)
 
RemovalStrategy parseStrategy (const std::string &strategyStr, TTree *tree)
 
template<class Jet >
vector< fjcore::PseudoJet > cluster (const vector< Jet > &jets, const double R)
 
template<class Jet >
bool overlappingJets (const vector< Jet > &jets)
 
void applyEventMixing (const vector< fs::path > &inputs1, const vector< fs::path > &inputs2, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0})
 
void applyNjetSkim (const vector< fs::path > &inputs, const fs::path &output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0})
 
template<class Jet >
std::vector< Jet > PhaseSpaceSelection (const std::vector< Jet > &jets, float minpt)
 
void getTPSobservables (const vector< fs::path > inputs, const fs::path output, const pt::ptree &config, const int steering, const DT::Slice slice={1, 0})
 

Enumeration Type Documentation

◆ RemovalStrategy

enum RemovalStrategy
strong
Enumerator
DeltaR 
AntikT 
None 
36 { DeltaR, AntikT, None };

Function Documentation

◆ applyEventMixing()

void DAS::TPS::applyEventMixing ( const vector< fs::path > &  inputs1,
const vector< fs::path > &  inputs2,
const fs::path &  output,
const pt::ptree &  config,
const int  steering,
const DT::Slice  slice = {1,0} 
)

Mix the jets from second input to first input to simulate DPS or TPS events. Overlapping jets are properly treated. The input must be taken from applyNjetSkim and must have the same isMC flag and pTcut.

Todo:
fix output logic
Todo:
Merge metainfos
Parameters
inputs1input ROOT files (n-tuples)
inputs2input ROOT files (n-tuples)
outputoutput ROOT file (n-tuple)
configconfig handled with `Darwin::Tools::options`
steeringparameters obtained from explicit options
slicenumber and index of slice
126  {1,0}
127  )
128 {
129  cout << __func__ << ' ' << slice << " start" << endl;
130 
131  DT::Flow flow1(steering, inputs1);
132  DT::Flow flow2(steering, inputs2);
133  auto tIn1 = flow1.GetInputTree(slice);
134  auto tIn2 = flow2.GetInputTree(slice);
135  auto tOut2 = flow2.GetOutputTree(output);
136  auto tOut1 = flow1.GetOutputTree(output);
137 
138  DT::MetaInfo metainfo1(tOut1);
139  DT::MetaInfo metainfo2(tOut2);
141  metainfo1.Check(config);
142  metainfo2.Check(config);
143  auto isMC = metainfo1.Get<bool>("flags", "isMC");
144  auto minpt = metainfo1.Get<float>("skims","jets","minpt");
145  auto R = metainfo1.Get<int>("flags","R");
146 
147  CheckConsistency(metainfo1, tIn1, metainfo2, tIn2);
148 
149  auto recEvent1 = flow1.GetBranchReadWrite<RecEvent>("recEvent");
150  auto recEvent2 = flow2.GetBranchReadOnly <RecEvent>("recEvent");
151  auto genEvent1 = isMC ? flow1.GetBranchReadWrite<GenEvent>("genEvent") : nullptr;
152  auto genEvent2 = isMC ? flow2.GetBranchReadOnly <GenEvent>("genEvent") : nullptr;
153  auto recJets1 = flow1.GetBranchReadWrite<vector<RecJet>>("recJets");
154  auto recJets2 = flow2.GetBranchReadOnly <vector<RecJet>>("recJets");
155  auto genJets1 = isMC ? flow1.GetBranchReadWrite<vector<GenJet>>("genJets") : nullptr;
156  auto genJets2 = isMC ? flow2.GetBranchReadOnly <vector<GenJet>>("genJets") : nullptr;
157 
158  const auto strategyStr = config.get<string>("corrections.event_mixing.overlap");
159  const auto strategy = parseStrategy(strategyStr, tIn1);
160 
161 
162  for (DT::Looper looper1(tIn1), looper2(tIn2); looper1() && looper2(); ++looper1, ++looper2) {
163  [[maybe_unused]]
164  static auto& cout = (steering & DT::verbose) ? ::cout : DT::dev_null;
165 
166  if (recJets1 && recJets2) {
167  // Merge input2's jets into input1's jets
168  recJets1->insert(recJets1->end(), recJets2->begin(), recJets2->end());
169  recEvent1->weights.front() *= recEvent2->weights.front();
170 
171  sort(recJets1->begin(), recJets1->end(), pt_sort); // sort again the jets by pt
172 
173  switch (strategy) {
174  case RemovalStrategy::DeltaR:
175  if (overlappingJets(*recJets1)) continue;
176  break;
177  case RemovalStrategy::AntikT:{
178  // reclustering the jets with anti-kt algorithm
179  vector<fjcore::PseudoJet> inclusive_recJets = cluster(*recJets1, R/10.0);
180  // Jet multiplicity may vary due to the reclustering.
181  // We only leave the event with unchanged jet multiplicity.
182  int nJets1 = PhaseSpaceSelection(*recJets1, minpt).size();
183  int nJets2 = PhaseSpaceSelection(inclusive_recJets, minpt).size();
184  if (nJets1 != nJets2) {
185  cout << "Jet multiplicity changed: " << nJets1 << " -> " << nJets2 << endl;
186  cout << "recJets: ";
187  for (const auto& jet : *recJets1) cout << jet.CorrPt() << " ";
188  cout << "\nAnti-kT: ";
189  for (const auto& jet : inclusive_recJets) cout << jet.pt() << " ";
190  cout << endl;
191  continue;
192  }
193  break;
194  }
195  case RemovalStrategy::None:;
196  }
197  }
198  if (isMC && genJets1 && genJets2) {
199  // Merge input2's jets into input1's jets
200  genJets1->insert(genJets1->end(), genJets2->begin(), genJets2->end());
201  genEvent1->weights.front() *= genEvent2->weights.front();
202 
203  sort(genJets1->begin(), genJets1->end(), pt_sort); // sort again the jets by pt
204 
205  switch (strategy) {
206  case RemovalStrategy::DeltaR:
207  if (overlappingJets(*genJets1)) continue;
208  break;
209  case RemovalStrategy::AntikT:{
210  // reclustering the jets with anti-kt algorithm
211  vector<fjcore::PseudoJet> inclusive_genJets = cluster(*genJets1, R/10.0);
212  // Jet multiplicity may vary due to the reclustering.
213  // We only leave the event with unchanged jet multiplicity.
214  int nJets1 = PhaseSpaceSelection(*genJets1, minpt).size();
215  int nJets2 = PhaseSpaceSelection(inclusive_genJets, minpt).size();
216  if (nJets1 != nJets2) {
217  cout << "Jet multiplicity changed: " << nJets1 << " -> " << nJets2 << endl;
218  cout << "genJets: ";
219  for (const auto& jet : *genJets1) cout << jet.CorrPt() << " ";
220  cout << "\nAnti-kT: ";
221  for (const auto& jet : inclusive_genJets) cout << jet.pt() << " ";
222  cout << endl;
223  continue;
224  }
225  break;
226  }
227  case RemovalStrategy::None:;
228  }
229  }
230 
231  if (steering & DT::fill) tOut1->Fill();
232  }
233 
234  metainfo1.Set<bool>("git", "complete", true);
235  cout << __func__ << ' ' << slice << " stop" << endl;
236 }

◆ applyNjetSkim()

void DAS::TPS::applyNjetSkim ( const vector< fs::path > &  inputs,
const fs::path &  output,
const pt::ptree &  config,
const int  steering,
const DT::Slice  slice = {1,0} 
)

Skims the input tree to keep only events with different jet multiplicity, with configurable pT thresholds for leading Njets.

Note
Drop the selection for genJets, as it will tighter the selection on rec level in MC samples than data. In case we only interested in the rec level in this stage, we can drop the gen level selection.
Parameters
inputsinput ROOT files (n-tuples)
outputoutput ROOT file (n-tuple)
configconfig handled with `Darwin::Tools::options`
steeringparameters obtained from explicit options
slicenumber and index of slice
41  {1,0}
42  )
43 {
44  cout << __func__ << ' ' << slice << " start" << endl;
45 
46  DT::Flow flow(steering, inputs);
47  auto tIn = flow.GetInputTree(slice);
48  auto [fOut, tOut] = flow.GetOutput(output);
49 
50  DT::MetaInfo metainfo(tOut);
51  metainfo.Check(config);
52  auto isMC = metainfo.Get<bool>("flags", "isMC");
53 
54  const auto minpt = config.get<float>("skims.jets.minpt");
55  metainfo.Set<float>("skims", "jets", "minpt", minpt);
56 
57  const auto Njets = config.get<int>("skims.jets.N");
58  metainfo.Set<int>("skims", "jets", "N", Njets);
59  cout << "Skimming events: Njets = " << Njets << "\t minpt > " << minpt << endl;
60 
61  auto recJets = flow.GetBranchReadOnly<vector<RecJet>>("recJets");
62  auto genJets = isMC ? flow.GetBranchReadOnly<vector<GenJet>>("genJets") : nullptr;
63  auto pileup = flow.GetBranchReadOnly<PileUp>("pileup");
64 
65  for (DT::Looper looper(tIn); looper(); ++looper) {
66  [[ maybe_unused ]]
67  static auto& cout = steering & DT::verbose ? ::cout : DT::dev_null;
68 
69  if (pileup->nVtx > 1) continue; // skip events with more than one vertex
70 
71  bool passRec = recJets && PhaseSpaceSelection(*recJets, minpt).size() == Njets;
72  bool passGen = genJets && PhaseSpaceSelection(*genJets, minpt).size() == Njets;
73 
74  if ((steering & DT::fill) && passRec) tOut->Fill();
77  }
78 
79  metainfo.Set<bool>("git", "complete", true);
80  cout << __func__ << ' ' << slice << " stop" << endl;
81 }

◆ CheckConsistency()

void DAS::TPS::CheckConsistency ( DT::MetaInfo metainfo1,
TTree *  tIn1,
DT::MetaInfo metainfo2,
TTree *  tIn2 
)

Check the consistency between two inputs make sure they have the same isMC flag and pTcut. The number of entries in the two input files doesn’t have to be the same, but the number of entries in the output file will be affected by the smaller one.

42  {
43  struct Dataset {
44  string name;
45  bool isMC;
46  int Njets;
47  float minpt;
48  long long entries;
49  } datasets[] = {
50  {"Input1", metainfo1.Get<bool>("flags", "isMC"), metainfo1.Get<int>("skims", "jets", "N"), metainfo1.Get<float>("skims", "jets", "minpt"), tIn1 ? tIn1->GetEntries() : 0},
51  {"Input2", metainfo2.Get<bool>("flags", "isMC"), metainfo2.Get<int>("skims", "jets", "N"), metainfo2.Get<float>("skims", "jets", "minpt"), tIn2 ? tIn2->GetEntries() : 0}
52  };
53  int minIndex = (datasets[0].entries < datasets[1].entries) ? 0 : 1;
54  cout << "+---------+------+-------+-------+-------------+\n"
55  << "| Dataset | isMC | Njets | pTcut | Entries |\n"
56  << "+---------+------+-------+-------+-------------+\n";
57  for (int i = 0; i < 2; i++) {
58  cout << "| " << setw(7) << left << datasets[i].name
59  << " | " << setw(4) << left << (datasets[i].isMC ? "Yes" : "No")
60  << " | " << setw(5) << left << datasets[i].Njets
61  << " | " << setw(5) << left << datasets[i].minpt
62  << " | " << setw(11 + (i == minIndex ? 9 : 0)) << right
63  << (i == minIndex ? orange + to_string(datasets[i].entries) + def : to_string(datasets[i].entries))
64  << " |\n";
65  }
66  cout << "+---------+------+-------+-------+-------------+\n" << flush;
67 
68  if (datasets[0].isMC != datasets[1].isMC)
69  BOOST_THROW_EXCEPTION( DE::BadInput("The isMC flag is inconsistent between inputs!", tIn1) );
70  if (datasets[0].minpt != datasets[1].minpt)
71  BOOST_THROW_EXCEPTION( DE::BadInput("The pTcut is inconsistent between inputs!", tIn1) );
72 }

◆ cluster()

vector<fjcore::PseudoJet> DAS::TPS::cluster ( const vector< Jet > &  jets,
const double  R 
)

Anti-kt clustering algorithm to recluster the jets. The jets are sorted by pT and the reclustered jets are returned.

89  {
90  vector<fjcore::PseudoJet> input_jets;
91  input_jets.reserve(jets.size()+1);
92  for (const auto& jet: jets) {
93  const auto& p4 = jet.CorrP4();
94  input_jets.push_back(fjcore::PseudoJet(p4.px(),p4.py(),p4.pz(),p4.E()));
95  }
96  fjcore::JetDefinition jet_def(fjcore::antikt_algorithm, R);
97  fjcore::ClusterSequence clust_seq(input_jets, jet_def);
98  vector<fjcore::PseudoJet> inclusive_jets = sorted_by_pt(clust_seq.inclusive_jets(0.0));
99  return inclusive_jets;
100 }

◆ getTPSobservables()

void DAS::TPS::getTPSobservables ( const vector< fs::path >  inputs,
const fs::path  output,
const pt::ptree &  config,
const int  steering,
const DT::Slice  slice = {1,0} 
)

Calculate the observables that can be used to caracterise 6 jets events.

Parameters
inputsinput ROOT files (n-tuples)
outputname of output root file containing the histograms
configconfig file from `DTOptions`
steeringsteering parameters from `DTOptions`
sliceslices for running
121  {1,0}
122  )
123 {
124  cout << __func__ << ' ' << slice << " start" << endl;
125 
126  DT::Flow flow(steering, inputs);
127  auto tIn = flow.GetInputTree(slice);
128  auto [fOut, tOut] = flow.GetOutput(output);
129 
130  DT::MetaInfo metainfo(tOut);
131  metainfo.Check(config);
132  auto isMC = metainfo.Get<bool>("flags", "isMC");
133 
134  const auto minpt = config.get<float>("skims.jets.minpt");
135  metainfo.Set<float>("skims", "jets", "minpt", minpt);
136 
137  auto rEv = flow.GetBranchReadOnly<RecEvent>("recEvent");
138  auto recJets = flow.GetBranchReadOnly<vector<RecJet>>("recJets");
139  auto gEv = isMC ? flow.GetBranchReadOnly<GenEvent>("genEvent") : nullptr;
140  auto genJets = isMC ? flow.GetBranchReadOnly<vector<GenJet>>("genJets") : nullptr;
141 
142  Hist genHist("gen"),
143  recHist("rec");
144 
145  for (DT::Looper looper(tIn); looper(); ++looper) {
146  [[ maybe_unused ]]
147  static auto& cout = steering & DT::verbose ? ::cout : DT::dev_null;
148 
149  MultiJets recMultijets(*recJets, minpt);
150  if (recMultijets) {
151  double evweight = rEv->weights.front();
152  if (isMC) evweight *= gEv->weights.front();
153  recHist.Fill(recMultijets, evweight);
154  }
155 
156  if (!isMC) continue;
157  MultiJets genMultijets(*genJets, minpt);
158  if (genMultijets) {
159  double evweight = gEv->weights.front();
160  genHist.Fill(genMultijets, evweight);
161  }
162  }
163 
164  recHist.Write(fOut);
165  if (isMC)
166  genHist.Write(fOut);
167  metainfo.Set<bool>("git", "complete", true);
168 
169  cout << __func__ << ' ' << slice << " end" << endl;
170 }

◆ overlappingJets()

bool DAS::TPS::overlappingJets ( const vector< Jet > &  jets)

Loop all possible jets combinations checking azimuthal difference to avioding overlapping jets.

106  {
107  for (size_t i = 0; i < jets.size(); ++i) {
108  for (size_t j = i + 1; j < jets.size(); ++j) {
109  if (DeltaR(jets[i].p4, jets[j].p4) < 0.4)
110  return true;
111  }
112  }
113  return false;
114 }

◆ parseStrategy()

RemovalStrategy DAS::TPS::parseStrategy ( const std::string &  strategyStr,
TTree *  tree 
)

Define the strategy to remove overlapping jets.

76  {
77  cout << "Removal strategy = " << strategyStr << endl;
78  if (strategyStr == "DeltaR") return RemovalStrategy::DeltaR;
79  else if (strategyStr == "antikt") return RemovalStrategy::AntikT;
80  else if (strategyStr == "none") return RemovalStrategy::None;
81 
82  BOOST_THROW_EXCEPTION(DE::BadInput(("Unrecognized strategy: " + strategyStr).c_str(), tree));
83 }

◆ PhaseSpaceSelection()

std::vector<Jet> DAS::TPS::PhaseSpaceSelection ( const std::vector< Jet > &  jets,
float  minpt 
)
24  {
25  std::vector<Jet> tempjets;
26  for (const auto& jet : jets) {
27  double eta;
28  if constexpr(has_p4<Jet>::value) {
29  eta = jet.p4.Eta();
30  } else {
31  eta = jet.eta();
32  }
33  if (jet.CorrPt() > minpt && eta < 5.0)
34  tempjets.push_back(jet);
35  }
36  return tempjets;
37 }
DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.name
name
Definition: DYToLL_M-50_13TeV_pythia8_cff_GEN_SIM_RECOBEFMIX_DIGI_L1_DIGI2RAW_L1Reco_RECO.py:48
Darwin::Tools::fill
@ fill
activate -f to fill the tree
Definition: Options.h:27
Darwin::Tools::Flow
User-friendly handling of input and output n-tuples.
Definition: Flow.h:78
Step::verbose
static bool verbose
Definition: Step.h:40
Step::def
static const char * def
Definition: Step.h:36
Darwin::Tools::UserInfo::Get
T Get(TList *mother, const char *key) const
Definition: UserInfo.h:75
Darwin::Tools::Looper
Facility to loop over a n-tuple, including parallelisation and printing.
Definition: Looper.h:22
DAS::PileUp::nVtx
int nVtx
number of vertices in the event
Definition: Event.h:103
Darwin::Tools::MetaInfo
Generic meta-information for n-tuple (including speficities to Darwin).
Definition: MetaInfo.h:68
DAS::TPS::cluster
vector< fjcore::PseudoJet > cluster(const vector< Jet > &jets, const double R)
Definition: applyEventMixing.cc:89
DAS::pt_sort
bool pt_sort(const PhysicsObject &j1, const PhysicsObject &j2)
Definition: toolbox.h:18
DAS::MN::minpt
static const double minpt
Definition: getMNobservables.cc:39
sorted_by_pt
std::vector< PseudoJet > sorted_by_pt(const std::vector< PseudoJet > &jets)
Definition: fjcore.cc:4063
Ntupliser_cfg.jets
string jets
Definition: Ntupliser_cfg.py:41
antikt_algorithm
@ antikt_algorithm
Definition: fjcore.hh:1040
Ntupliser_cfg.config
config
Definition: Ntupliser_cfg.py:317
DAS::TPS::overlappingJets
bool overlappingJets(const vector< Jet > &jets)
Definition: applyEventMixing.cc:106
orange
static const char * orange
Definition: colours.h:6
DAS::TPS::RemovalStrategy::AntikT
@ AntikT
pileup
DAS::PileUp pileup
Definition: classes.h:27
DAS::TPS::PhaseSpaceSelection
std::vector< Jet > PhaseSpaceSelection(const std::vector< Jet > &jets, float minpt)
Definition: common.h:24
Step::None
@ None
iterate until max value is reached
Definition: Step.h:431
Ntupliser_cfg.isMC
dictionary isMC
Definition: Ntupliser_cfg.py:61
DAS::TPS::RemovalStrategy::DeltaR
@ DeltaR
DAS::TPS::parseStrategy
RemovalStrategy parseStrategy(const std::string &strategyStr, TTree *tree)
Define the strategy to remove overlapping jets.
Definition: applyEventMixing.cc:76
DAS::TPS::CheckConsistency
void CheckConsistency(DT::MetaInfo &metainfo1, TTree *tIn1, DT::MetaInfo &metainfo2, TTree *tIn2)
Definition: applyEventMixing.cc:42
jercExample.inputs
def inputs
Definition: jercExample.py:118
Darwin::Tools::dev_null
static std::ostream dev_null(nullptr)
to redirect output stream to nowhere
Darwin::Exceptions::BadInput
Generic exception for ill-defined input (before the event loop).
Definition: exceptions.h:83
jmarExample.eta
eta
DeepAK8/ParticleNet tagging.
Definition: jmarExample.py:19