ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Reconstruction
Jet
JetRec
Root
PseudoJetContainer.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3
*/
4
5
// PseudoJetContainer.cxx
6
7
#include "
JetRec/PseudoJetContainer.h
"
8
#include "
JetRec/IConstituentExtractor.h
"
9
#include "
JetEDM/VertexIndexedConstituentUserInfo.h
"
10
#include <map>
11
#include "
xAODJet/Jet.h
"
12
#include "fastjet/PseudoJet.hh"
13
#include "
JetRec/LineFormatter.h
"
// helper class for debug printing
14
#include <sstream>
15
#include <ios>
16
#include <iostream>
17
#include <exception>
18
19
using
fastjet::PseudoJet;
20
21
PseudoJetContainer::PseudoJetContainer
() {
22
checkInvariants
(
"PseudoJetContainer()"
);
23
}
24
25
PseudoJetContainer::PseudoJetContainer
(std::unique_ptr<const IConstituentExtractor> c,
26
const
std::vector<PseudoJet> & vecPJ,
27
bool
debug
){
28
29
m_debug
=
debug
;
30
31
if
(vecPJ.empty()){
32
m_emptyExtractors
.insert(std::move(c));
33
return
;
34
}
35
36
if
(
m_debug
){
checkInConstituents
(vecPJ,
"constuctor"
);}
37
m_allConstituents
= vecPJ;
38
39
// the limits of the Extractor index range correposnd to the
40
// numbering of the EDM objects in th extractors.
41
m_extractorRanges
.emplace_back(0,
42
vecPJ.back().user_index(),
43
std::move(c));
44
if
(
m_debug
){
checkInvariants
(
"PseudoJetContainer(vcPJ, c)"
);}
45
}
46
47
bool
48
PseudoJetContainer::extractConstituents
(
xAOD::Jet
&
jet
,
49
const
std::vector<PseudoJet>& inConstits)
const
50
{
51
52
// check container integrity if m_debug == true
53
if
(
m_debug
){
checkInvariants
(
"extractConstituents()"
);}
54
55
// set up mapping to acquire the EDM indices by Extractor
56
std::map<const IConstituentExtractor*, std::vector<int>> sorter;
57
58
// add an entry into the sorter for each extractor.
59
// this way each extractor will be called, possibly with
60
// an empty index list - this will happen if no pseudojet correponding
61
// to the extractor is received. But an empty list is used
62
// by the extractors to fill zeros into the jet.
63
for
(
const
auto
& er :
m_extractorRanges
){
64
sorter.emplace(er.m_e.get(), std::vector<int>{});
65
}
66
67
// see header file for explanation of empty extractors.
68
for
(
const
auto
& e :
m_emptyExtractors
){
69
sorter.emplace(e.get(), std::vector<int>{});
70
}
71
72
// check whether inputs are lgal if m_debug == true
73
if
(
m_debug
){
checkInConstituents
(inConstits,
"extractConsituents()"
);}
74
75
for
(
const
auto
& pj : inConstits){
76
77
int
pj_ind = pj.user_index();
78
79
// fastjet clustering may add in pseudojets with the default (-1) index.
80
// ignore these.
81
if
(pj_ind == -1) {
continue
;}
82
83
// The index of the pseudojet and the low limit
84
// the extractorRange table (which acts as an offset), identifies which
85
// extractorRanges entry to use, and the EDM object that corrsponds to the
86
// pseudojet.
87
88
auto
e = std::find_if(
m_extractorRanges
.begin(),
89
m_extractorRanges
.end(),
90
[pj_ind](
const
ExtractorRange
&
r
){
91
return pj_ind >= r.m_lo and pj_ind <= r.m_hi;});
92
93
if
(e ==
m_extractorRanges
.end()){
return
false
;}
94
95
sorter[(*e).m_e.get()].push_back(pj_ind - (*e).m_lo);
96
}
97
98
// send the jet to the each extractor with a vector of EDM
99
// indices for that extractor
100
for
(
const
auto
& s : sorter){s.first -> addToJet(
jet
, s.second);}
101
return
true
;
102
}
103
104
105
// fill xAOD jet with constit&ghosts extracted from final PSeudoJet
106
bool
PseudoJetContainer::extractConstituents
(
xAOD::Jet
&
jet
,
107
const
PseudoJet
& finalPJ)
const
{
108
109
std::vector<PseudoJet> inConstituents = finalPJ.constituents();
110
return
extractConstituents
(
jet
, inConstituents);
111
}
112
113
// fill xAOD jet with correct by-vertex consituents and ghosts
114
bool
PseudoJetContainer::extractByVertexConstituents
(
xAOD::Jet
&
jet
,
const
PseudoJet
& finalPJ,
const
xAOD::Vertex
* vertex)
const
{
115
std::vector<PseudoJet> allInConstituents = finalPJ.constituents();
116
std::vector<PseudoJet> byVertexConstituents;
117
for
(
PseudoJet
& constituent: allInConstituents){
118
if
(constituent.has_user_info<
jet::VertexIndexedConstituentUserInfo
>()){
119
const
jet::VertexIndexedConstituentUserInfo
& userInfo = constituent.user_info<
jet::VertexIndexedConstituentUserInfo
>();
120
const
xAOD::Vertex
* originVertex = userInfo.
vertex
();
121
122
// if constituent has relevant user info, only accept it if it matches the vertex in question
123
if
(originVertex == vertex){
124
byVertexConstituents.emplace_back(constituent);
125
}
126
}
127
else
{
128
// this must be a ghost constituent, since it does not have userinfo
129
byVertexConstituents.emplace_back(constituent);
130
}
131
}
132
return
extractConstituents
(
jet
, byVertexConstituents);
133
}
134
135
const
std::vector<PseudoJet>*
PseudoJetContainer::casVectorPseudoJet
()
const
{
136
if
(
m_debug
){
checkInvariants
(
"asVectorPseudoJet()"
);}
137
return
&
m_allConstituents
;
138
}
139
140
std::vector<PseudoJet>*
PseudoJetContainer::casVectorPseudoJet
() {
141
if
(
m_debug
){
checkInvariants
(
"asVectorPseudoJet()"
);}
142
return
&
m_allConstituents
;
143
}
144
145
void
PseudoJetContainer::append
(
const
PseudoJetContainer
* other) {
146
// Adds the extractors and pseudo jets for other to this container.
147
148
// add the other extractor and its range to the ExtractorRanges table
149
int
offset =
m_extractorRanges
.empty() ? 0 :
m_extractorRanges
.back().m_hi+1;
150
151
std::transform(other->m_extractorRanges.begin(),
152
other->m_extractorRanges.end(),
153
std::back_inserter(
m_extractorRanges
),
154
[offset](
const
ExtractorRange
& e){return e.bump(offset);});
155
156
// copy over the pseudojets for the extractor being processed,
157
// and set the user index to match th extractorRange limits.
158
159
160
std::transform(other->m_allConstituents.begin(),
161
other->m_allConstituents.end(),
162
std::back_inserter(
m_allConstituents
),
163
[offset](fastjet::PseudoJet pj){
164
pj.set_user_index(pj.user_index() + offset);return pj;}
165
);
166
167
for
(
const
auto
&e : other->m_emptyExtractors){
m_emptyExtractors
.emplace(e->clone());}
168
169
if
(
m_debug
){
checkInvariants
(
"append()"
);}
170
}
171
172
std::string
PseudoJetContainer::toString
(
int
level,
int
extLevel)
const
{
173
std::ostringstream oss{
"PseudoJetContainer at: "
, std::ios::ate};
174
oss <<
this
175
<<
"\ndump levels: "
<< level <<
" "
<< extLevel <<
'\n'
176
<<
" ExtractorRanges ranges: ["
<<
m_extractorRanges
.size() <<
"] "
;
177
for
(
const
auto
& er :
m_extractorRanges
){
178
oss <<
"("
<< er.m_lo <<
","
<<er.m_hi <<
"), "
;
179
}
180
181
oss <<
" empty extractors: "
<<
m_emptyExtractors
.size();
182
oss <<
" Pseudojets: "
<<
m_allConstituents
.size();
183
184
if
(level > 0){
185
oss <<
"\n Extractor dump: \n"
;
186
for
(
const
auto
& er :
m_extractorRanges
){
187
oss <<
"Extractor at ["
;
188
oss << er.m_e.get();
189
oss <<
"]\n"
;
190
oss << er.m_e->toString(extLevel) <<
'\n'
;
191
}
192
}
193
194
if
(level > 1){ oss <<
dumpPseudoJets
();}
195
196
return
oss.str();
197
}
198
199
std::string
PseudoJetContainer::dumpPseudoJets
()
const
{
200
std::ostringstream oss{
"PseudoJetContainer at: "
, std::ios::ate};
201
oss <<
"\n PseudoJet energies\n"
;
202
for
(
const
auto
& p :
m_allConstituents
){
203
oss <<
"pseudojet user ind "
<< p.user_index()
204
<<
" E "
<< p.e() <<
" "
<< p.eta() <<
'\n'
;
205
}
206
207
return
oss.str();
208
}
209
210
211
bool
PseudoJetContainer::checkInvariants
(
const
std::string& from)
const
{
212
213
if
(!
m_debug
){
return
true
;}
214
215
std::ostringstream
216
oss(
"PseudoJetContainer checkInvariants called from: "
,
217
std::ios::ate);
218
oss << from <<
" "
;
219
220
if
(
m_extractorRanges
.empty()){
221
if
(!
m_allConstituents
.empty()){
222
oss <<
"No extractors, but pseudojets present"
;
223
return
bad_invariants_exit
(oss);
224
}
225
return
true
;
226
}
227
228
// have at least one extractor
229
// m_lo == m_hi possible if an empty EDM container has been read in.
230
for
(
const
auto
& ex :
m_extractorRanges
){
231
if
(ex.m_lo < 0 or ex.m_lo > ex.m_hi){
232
oss <<
"bad extractor limits: "
<< ex.m_lo <<
" "
<< ex.m_hi;
233
return
bad_invariants_exit
(oss);
234
}
235
}
236
237
// have at least one extractor with non-zero limits
238
auto
npj =
m_allConstituents
.size();
239
auto
uExtCount = (
m_extractorRanges
.back()).m_hi;
240
if
(uExtCount < 0){
241
oss <<
" Illegal extractor range limit "
<< uExtCount;
242
return
bad_invariants_exit
(oss);
243
}
244
245
std::size_t uuExtCount = uExtCount;
246
247
//The user index for a pseudojet is an index into the EDM objet
248
// array. The comparison here is between th size of the PseudoJet
249
// array and the index of th EDM objects. When each EDM object
250
// gives rise to a PsedoJet, these numbers differ by 1.
251
// Not all EDM objcts give rise to a PseudoJet, so an inequality
252
// is tested here.
253
if
(npj > uuExtCount + 1){
254
oss <<
" Mismatch between pseudo jet count/upper Extractor limit "
255
<< npj <<
"/"
<< uuExtCount;
256
return
bad_invariants_exit
(oss);
257
}
258
259
// have pseudoJets
260
261
auto
firstInd =
m_allConstituents
[0].user_index();
262
if
(firstInd != 0){
263
oss <<
" first pseudojet does not have index 0 "
<< firstInd;
264
return
bad_invariants_exit
(oss);
265
}
266
267
auto
nent =
m_extractorRanges
.size();
268
269
for
(std::size_t i = 0; i < nent-1; ++i){
270
auto
cur =
m_extractorRanges
[i];
271
auto
next =
m_extractorRanges
[i+1];
272
if
(cur.m_hi != next.m_lo - 1){
273
oss <<
"Hi limit for extractor "
<< i
274
<<
" != low limit for extractor "
<< i+1;
275
return
bad_invariants_exit
(oss);
276
}
277
}
278
279
if
(!
checkPseudoJetVector
(
m_allConstituents
,
"checkInvariants()"
)) {
280
return
bad_invariants_exit
(oss);
281
}
282
283
for
(
const
auto
& pj :
m_allConstituents
){
284
try
{
285
pj.e();
286
}
catch
(...){
287
oss <<
"PseudoJet.e() fails of PJ in m_allConstituents"
;
288
return
bad_invariants_exit
(oss);
289
}
290
}
291
292
for
(
const
ExtractorRange
& er :
m_extractorRanges
){
293
if
(!((er.m_e)->checkIntegrity())){
294
oss <<
"IConstituentExtractor fails integrity test"
;
295
return
bad_invariants_exit
(oss);
296
}
297
}
298
299
oss <<
"No of PseudoJets: "
<<
m_allConstituents
.size()
300
<<
" No of Extractors "
<<
m_extractorRanges
.size() <<
" all OK"
;
301
302
return
true
;
303
}
304
305
bool
PseudoJetContainer::checkPseudoJetVector
(
const
std::vector<PseudoJet>& v,
306
const
std::string& from)
const
{
307
308
// Pseudojets in th vector v contain the indices into the
309
// the EDM object vector held in the Extractors. If there is more than
310
// one extractor, an extractor dependent offset is added to index.
311
// The indices should be ordered, and start from a value >= 0.
312
313
if
(!
m_debug
){
return
true
;}
314
315
std::ostringstream
316
oss(
"PseudoJetContainer checkPseudoJetVector called from: "
,
317
std::ios::ate);
318
oss << from <<
" "
;
319
320
if
(v.empty()){
321
oss <<
"Empty pseudojet vector "
;
322
return
true
;
// empty not a problem
323
}
324
325
oss <<
"PseudoJetVector energy dump:\n"
;
326
std::vector<float> energies;
327
energies.reserve(v.size());
328
std::transform(v.begin(),
329
v.end(),
330
std::back_inserter(energies),
331
[](
const
PseudoJet
& p){return p.e();});
332
333
LineFormatter
formatter(10);
// dump the energies, 10 values/line.
334
oss << formatter(energies);
335
336
337
bool
ok{
true
};
338
if
(v[0].user_index() < 0){
339
ok =
false
;
340
oss <<
"First pj has index < 0: "
<< v[0].user_index();
341
}
342
343
std::vector<int> indices(v.size());
344
std::transform(v.begin(),
345
v.end(),
346
std::back_inserter(indices),
347
[](
const
PseudoJet
& p){return p.user_index();});
348
349
if
(!std::is_sorted(indices.begin(), indices.end())){
350
oss <<
"Pseudojets out of order "
;
351
ok =
false
;
352
}
353
354
if
(ok){oss << v.size() <<
" checked ok"
;}
355
356
return
ok;
357
}
358
359
bool
360
PseudoJetContainer::checkInConstituents
(
const
std::vector<PseudoJet>& v,
361
const
std::string& from)
const
{
362
363
if
(!
m_debug
){
return
true
;}
364
365
std::ostringstream
366
oss(
"PseudoJetContainer checkInConstituents called from: "
,
367
std::ios::ate);
368
oss << from <<
" "
;
369
oss << v.size() <<
" entries\n"
;
370
371
std::vector<double> energies;
372
energies.reserve(v.size());
373
std::transform(v.begin(),
374
v.end(),
375
std::back_inserter(energies),
376
[](
const
PseudoJet
& p){return p.e();});
377
378
379
LineFormatter
formatter(10);
// dump the energies, 10 values/line.
380
oss << formatter(energies);
381
382
for
(
const
auto
& pj: v){
383
if
(pj.user_index() == -1){oss <<
"PJ index -1, E() "
<< pj.E() <<
'\n'
;}
384
}
385
386
std::vector<int> indices;
387
indices.reserve(v.size());
388
std::transform(v.begin(),
389
v.end(),
390
std::back_inserter(indices),
391
[](
const
PseudoJet
& p){return p.user_index();});
392
393
oss <<
"PseudoJet indices\n"
;
394
oss << formatter(indices);
395
396
397
std::map<int, int> counter;
398
if
(!
m_extractorRanges
.empty()) {
399
int
lo =
m_extractorRanges
[0].m_lo;
400
int
hi =
m_extractorRanges
.back().m_hi;
401
402
for
(
auto
ind : indices){
403
// ind = -1 pseudojets can be produced by fastjet.
404
if
(ind == -1){
continue
;}
405
if
(ind < lo or ind > hi){++(counter[ind]);}
406
}
407
}
408
409
bool
bad
= !counter.empty();
410
411
if
(
bad
){
412
oss <<
"Out of range values[counts]: "
;
413
414
for
(
auto
ent: counter){oss << ent.first <<
"/"
<< ent.second <<
'\n'
;}
415
oss <<
"Extractor ranges: \n"
;
416
for
(
const
auto
& er:
m_extractorRanges
){
417
oss << er.m_lo <<
" "
<< er.m_hi <<
'\n'
;
418
}
419
420
bad_invariants_exit
(oss);
421
}
422
423
424
return
true
;
425
}
426
427
bool
428
PseudoJetContainer::bad_invariants_exit
(
const
std::ostringstream& oss)
const
{
429
430
auto
errMsg = oss.str();
431
432
if
(
m_debug
) {
433
std::cerr << errMsg <<
'\n'
;
434
throw
std::runtime_error(errMsg);
435
}
436
437
return
false
;
438
}
439
440
std::size_t
PseudoJetContainer::size
()
const
{
441
return
m_allConstituents
.size();
442
}
443
444
bool
PseudoJetContainer::debug
()
const
{
return
m_debug
;}
445
void
PseudoJetContainer::debug
(
bool
b) {
m_debug
= b;}
446
std::ostream&
operator <<
(std::ostream& os,
const
PseudoJetContainer
& c){
447
os << c.toString(0);
448
return
os;
449
}
Jet.h
IConstituentExtractor.h
LineFormatter.h
operator<<
std::ostream & operator<<(std::ostream &os, const PseudoJetContainer &c)
Definition
PseudoJetContainer.cxx:446
PseudoJetContainer.h
bad
@ bad
Definition
SUSYToolsTester.cxx:95
VertexIndexedConstituentUserInfo.h
LineFormatter
Definition
LineFormatter.h:14
PseudoJetContainer::m_emptyExtractors
std::set< std::unique_ptr< const IConstituentExtractor > > m_emptyExtractors
Definition
PseudoJetContainer.h:146
PseudoJetContainer::m_debug
bool m_debug
Definition
PseudoJetContainer.h:148
PseudoJetContainer::extractByVertexConstituents
bool extractByVertexConstituents(xAOD::Jet &jet, const PseudoJet &finalPJ, const xAOD::Vertex *vertex) const
Definition
PseudoJetContainer.cxx:114
PseudoJetContainer::m_allConstituents
std::vector< PseudoJet > m_allConstituents
Definition
PseudoJetContainer.h:96
PseudoJetContainer::checkInConstituents
bool checkInConstituents(const std::vector< PseudoJet > &, const std::string &) const
Definition
PseudoJetContainer.cxx:360
PseudoJetContainer::checkInvariants
bool checkInvariants(const std::string &) const
Definition
PseudoJetContainer.cxx:211
PseudoJetContainer::casVectorPseudoJet
const std::vector< PseudoJet > * casVectorPseudoJet() const
Definition
PseudoJetContainer.cxx:135
PseudoJetContainer::m_extractorRanges
std::vector< ExtractorRange > m_extractorRanges
Definition
PseudoJetContainer.h:140
PseudoJetContainer::size
std::size_t size() const
Definition
PseudoJetContainer.cxx:440
PseudoJetContainer::PseudoJetContainer
PseudoJetContainer()
Definition
PseudoJetContainer.cxx:21
PseudoJetContainer::append
void append(const PseudoJetContainer *)
Definition
PseudoJetContainer.cxx:145
PseudoJetContainer::PseudoJet
fastjet::PseudoJet PseudoJet
Definition
PseudoJetContainer.h:50
PseudoJetContainer::bad_invariants_exit
bool bad_invariants_exit(const std::ostringstream &) const
Definition
PseudoJetContainer.cxx:428
PseudoJetContainer::debug
bool debug() const
Definition
PseudoJetContainer.cxx:444
PseudoJetContainer::dumpPseudoJets
std::string dumpPseudoJets() const
Definition
PseudoJetContainer.cxx:199
PseudoJetContainer::toString
std::string toString(int level, int extLevel=0) const
Definition
PseudoJetContainer.cxx:172
PseudoJetContainer::checkPseudoJetVector
bool checkPseudoJetVector(const std::vector< PseudoJet > &, const std::string &) const
Definition
PseudoJetContainer.cxx:305
PseudoJetContainer::extractConstituents
bool extractConstituents(xAOD::Jet &, const std::vector< PseudoJet > &) const
Definition
PseudoJetContainer.cxx:48
jet::VertexIndexedConstituentUserInfo
Definition
VertexIndexedConstituentUserInfo.h:16
jet::VertexIndexedConstituentUserInfo::vertex
const xAOD::Vertex * vertex() const
Returns the associated vertex if this constit is a track. Else returns null. */.
Definition
VertexIndexedConstituentUserInfo.h:28
r
int r
Definition
globals.cxx:22
jet
Definition
JetCalibTools_PlotJESFactors.cxx:23
xAOD::Jet
Jet_v1 Jet
Definition of the current "jet version".
Definition
Event/xAOD/xAODJet/xAODJet/Jet.h:17
xAOD::Vertex
Vertex_v1 Vertex
Define the latest version of the vertex class.
Definition
Event/xAOD/xAODTracking/xAODTracking/Vertex.h:16
PseudoJetContainer::ExtractorRange
Definition
PseudoJetContainer.h:105
Generated on
for ATLAS Offline Software by
1.17.0