Bug Summary

File:/volatile/halld/gluex/nightly/2024-04-23/Linux_CentOS7.7-x86_64-gcc4.8.5/halld_recon/src/libraries/ANALYSIS/DSourceCombo.h
Location:line 460, column 2
Description:Value stored to 'locCharge' is never read

Annotated Source Code

1#ifndef DSourceCombo_h
2#define DSourceCombo_h
3
4#include <map>
5#include <vector>
6#include <tuple>
7#include <memory>
8#include <algorithm>
9
10#include "JANA/JObject.h"
11#include "JANA/JEventLoop.h"
12
13#include "particleType.h"
14#include "DResettable.h"
15
16#include "PID/DNeutralShower.h"
17
18using namespace std;
19using namespace jana;
20
21namespace DAnalysis
22{
23
24/****************************************************** DEFINE LAMBDAS, USING STATEMENTS, DECLARE FUNCTIONS *******************************************************/
25
26//forward declarations
27class DSourceComboInfo;
28class DSourceCombo;
29
30//DSourceComboUse is what the combo is USED for (the decay of Particle_t (if Unknown then is just a grouping)
31//signed char: vertex-z bin of the final state (combo contents)
32//bool: true/false if has/doesn't-have missing decay product (is always false if decay pid == Unknown)
33//last pid: Rescattering Target PID (target excluded for 1st step) //is always Unknown if decay pid == Unknown)
34using DSourceComboUse = tuple<Particle_t, signed char, const DSourceComboInfo*, bool, Particle_t>; //e.g. Pi0, zbin, -> 2g, false, Unknown
35using DSourceCombosByUse_Small = vector<pair<DSourceComboUse, vector<const DSourceCombo*>>>;
36
37//DECLARE NAMESPACE-SCOPE FUNCTIONS
38vector<const JObject*> Get_SourceParticles(const vector<pair<Particle_t, const JObject*>>& locSourceParticles, Particle_t locPID = Unknown);
39vector<pair<Particle_t, const JObject*>> Get_SourceParticles_ThisVertex(const DSourceCombo* locSourceCombo, Charge_t locCharge = d_AllCharges);
40vector<const DSourceCombo*> Get_SourceCombos_ThisVertex(const DSourceCombo* locSourceCombo);
41vector<pair<DSourceComboUse, vector<const DSourceCombo*>>> Get_SourceCombosAndUses_ThisVertex(const DSourceCombo* locSourceCombo);
42Charge_t Get_ChargeContent(const DSourceComboInfo* locSourceComboInfo);
43bool Get_HasMassiveNeutrals(const DSourceComboInfo* locComboInfo);
44const JObject* Get_SourceParticle_ThisStep(const DSourceCombo* locSourceCombo, Particle_t locPID, size_t locInstance, size_t& locPIDCountSoFar);
45
46/************************************************************** DEFINE CLASSES ***************************************************************/
47
48//In theory, for safety, dynamically-allocated objects should be stored in a shared_ptr
49//However, the combos take a TON of memory, and a shared_ptr<T*> takes 3x the memory of a regular T* pointer
50//The info objects will exist for the life of the program, and so don't need to be recycled to a resource pool.
51//The combo objects will be recycled after every event into a resource pool.
52
53//If we REALLY need the memory, we can store these things in std::array instead of vector
54//These classes would need to have template parameters for the array sizes, and have a common base class
55//However, the base class would have to return either vectors (need to convert) or raw pointers (need bounds checking) instead of std::arrays (since type unknown to base class)
56//So it would require more CPU.
57
58//THE MOST NUMBER OF PARTICLES OF A GIVEN TYPE IS 255 (# stored in unsigned char)
59class DSourceComboInfo
60{
61 public:
62
63 //FORWARD DECLARE COMPARISON STRUCTS
64 struct DCompare_ParticlePairPIDs;
65 struct DCompare_FurtherDecays;
66
67 //CONSTRUCTOR
68 DSourceComboInfo(void) = delete;
69 DSourceComboInfo(const vector<pair<Particle_t, unsigned char>>& locNumParticles, const vector<pair<DSourceComboUse, unsigned char>>& locFurtherDecays = {});
70
71 //OPERATORS
72 bool operator< (const DSourceComboInfo& rhs) const;
73
74 //GET MEMBERS
75 vector<pair<Particle_t, unsigned char>> Get_NumParticles(bool locEntireChainFlag = false) const;
76 vector<pair<DSourceComboUse, unsigned char>> Get_FurtherDecays(void) const{return dFurtherDecays;}
77
78 //definitions of negative values for any particle index //in order such that operator< returns order expected for string (e.g. gp->...)
79 //Note: If the vertex is UnknowABLE, the bin for the parent vertex is chosen. If the production vertex is Unknowable, then the center of the target is used.
80 static signed char Get_VertexZIndex_OutOfRange(void){return -3;}
81 static signed char Get_VertexZIndex_ZIndependent(void){return -2;}
82 static signed char Get_VertexZIndex_Unknown(void){return -1;}
83
84 private:
85
86 //don't have decaying PID a direct member of this combo info
87 //e.g. for a 2g pair, it has no idea whether or not it came from a Pi0, an eta, through direct production, etc.
88 //this way, e.g., the 2g combos can be used for ANY of those possibilities, without creating new objects
89 //it is the responsibility of the containing object to know what the combos are used for: DSourceComboUse
90
91 vector<pair<Particle_t, unsigned char>> dNumParticles;
92 vector<pair<DSourceComboUse, unsigned char>> dFurtherDecays; //unsigned char: # of (e.g.) pi0s, etc.
93};
94
95inline bool operator<(const DSourceComboUse& lhs, const DSourceComboUse& rhs)
96{
97 //this puts mixed-charge first, then fully-neutral, then fully-charged
98
99 //first, special case of nullptr (guard against it)
100 if((std::get<2>(lhs) == nullptr) || (std::get<2>(rhs) == nullptr))
101 {
102 if(std::get<2>(lhs) != std::get<2>(rhs))
103 return (std::get<2>(lhs) == nullptr);
104 if(std::get<3>(lhs) != std::get<3>(rhs))
105 return (std::get<3>(lhs) < std::get<3>(rhs));
106 if(std::get<4>(lhs) != std::get<4>(rhs))
107 return (std::get<4>(lhs) < std::get<4>(rhs));
108
109 if(std::get<0>(lhs) == std::get<0>(rhs))
110 {
111 if(std::get<1>(lhs) == std::get<1>(rhs))
112 return false;
113 else
114 return std::get<1>(lhs) > std::get<1>(rhs);
115 }
116 if(ParticleMass(std::get<0>(lhs)) == ParticleMass(std::get<0>(rhs)))
117 return std::get<0>(lhs) > std::get<0>(rhs);
118 return (ParticleMass(std::get<0>(lhs)) > ParticleMass(std::get<0>(rhs)));
119 }
120
121 auto locChargeContent_LHS = Get_ChargeContent(std::get<2>(lhs));
122 auto locChargeContent_RHS = Get_ChargeContent(std::get<2>(rhs));
123 if(locChargeContent_LHS != locChargeContent_RHS)
124 return locChargeContent_LHS > locChargeContent_RHS;
125
126 if(std::get<3>(lhs) != std::get<3>(rhs))
127 return (std::get<3>(lhs) < std::get<3>(rhs));
128 if(std::get<4>(lhs) != std::get<4>(rhs))
129 return (std::get<4>(lhs) < std::get<4>(rhs));
130
131 //within each of those, it puts the most-massive particles first
132 if(std::get<0>(lhs) == std::get<0>(rhs))
133 {
134 if(std::get<1>(lhs) == std::get<1>(rhs))
135 return *std::get<2>(rhs) < *std::get<2>(lhs);
136 else
137 return std::get<1>(lhs) > std::get<1>(rhs);
138 }
139 if(ParticleMass(std::get<0>(lhs)) == ParticleMass(std::get<0>(rhs)))
140 return std::get<0>(lhs) > std::get<0>(rhs);
141 return (ParticleMass(std::get<0>(lhs)) > ParticleMass(std::get<0>(rhs)));
142}
143
144struct DSourceComboInfo::DCompare_ParticlePairPIDs
145{
146 bool operator()(const pair<Particle_t, unsigned char>& lhs, const pair<Particle_t, unsigned char>& rhs) const{return lhs.first < rhs.first;} //sort
147 bool operator()(const pair<Particle_t, unsigned char>& lhs, Particle_t rhs) const{return lhs.first < rhs;} //lookup
148 bool operator()(Particle_t lhs, const pair<Particle_t, unsigned char>& rhs) const{return lhs < rhs.first;} //lookup
149};
150
151struct DSourceComboInfo::DCompare_FurtherDecays
152{
153 bool operator()(const pair<DSourceComboUse, unsigned char>& lhs, const pair<DSourceComboUse, unsigned char>& rhs) const{return DAnalysis::operator<(lhs.first, rhs.first);} //sort
154 bool operator()(const pair<DSourceComboUse, unsigned char>& lhs, DSourceComboUse rhs) const{return DAnalysis::operator<(lhs.first, rhs);} //lookup
155 bool operator()(DSourceComboUse lhs, const pair<DSourceComboUse, unsigned char>& rhs) const{return DAnalysis::operator<(lhs, rhs.first);} //lookup
156};
157
158class DSourceCombo : public DResettable
159{
160 public:
161
162 //FORWARD DECLARE COMPARISON STRUCT
163 struct DCompare_FurtherDecays;
164
165 //CONSTRUCTOR
166 DSourceCombo(void) = default;
167 DSourceCombo(const vector<pair<Particle_t, const JObject*>>& locSourceParticles, const DSourceCombosByUse_Small& locFurtherDecayCombos, bool locIsZIndependent = false);
168
169 //SET MEMBERS
170 void Set_Members(const vector<pair<Particle_t, const JObject*>>& locSourceParticles, const DSourceCombosByUse_Small& locFurtherDecayCombos, bool locIsZIndependent = false);
171 void Reset(void);
172 void Release(void){Reset();};
173
174 //GET MEMBERS
175 vector<pair<Particle_t, const JObject*>> Get_SourceParticles(bool locEntireChainFlag = false, Charge_t locCharge = d_AllCharges) const;
176 DSourceCombosByUse_Small Get_FurtherDecayCombos(void) const{return dFurtherDecayCombos;}
177 bool Get_IsComboingZIndependent(void) const{return dIsComboingZIndependent;}
178
179 private:
180
181 //FYI, if use PID is unknown: Vector is guaranteed to be size 1, and none of ITS further decays can have an unknown use PID
182 //Note: Either:
183 //1) The entire content is one PID
184 //2) There is at most one particle of each PID
185 //Otherwise, groupings of 2+ (e.g. 2pi-) will be in the further-decay section (X -> 2pi+)
186
187 //particles & decays
188 vector<pair<Particle_t, const JObject*>> dSourceParticles; //original DNeutralShower or DChargedTrack
189 DSourceCombosByUse_Small dFurtherDecayCombos; //vector is e.g. size 3 if 3 pi0s needed
190
191 //everything is z-dependent for massive neutrals.
192 //however the momentum is SO z-dependent, that we can't cut on it until the end when we have the final vertex, AFTER comboing
193 //a mere z-bin is not enough.
194 //So, as far as COMBOING is concerned, massive neutrals are Z-INDEPENDENT
195 bool dIsComboingZIndependent = false; //is false for BCAL photons
196};
197
198struct DSourceCombo::DCompare_FurtherDecays
199{
200 bool operator()(const pair<DSourceComboUse, vector<const DSourceCombo*>>& lhs, const pair<DSourceComboUse, vector<const DSourceCombo*>>& rhs) const{return DAnalysis::operator<(lhs.first, rhs.first);} //sort
201 bool operator()(const pair<DSourceComboUse, vector<const DSourceCombo*>>& lhs, DSourceComboUse rhs) const{return DAnalysis::operator<(lhs.first, rhs);} //lookup
202 bool operator()(DSourceComboUse lhs, const pair<DSourceComboUse, vector<const DSourceCombo*>>& rhs) const{return DAnalysis::operator<(lhs, rhs.first);} //lookup
203};
204
205struct DSourceComboChecker_ReusedParticle
206{
207 //returns true if a particle WAS reused
208 bool operator()(const DSourceCombo* locCombo) const
209 {
210 auto locParticles = DAnalysis::Get_SourceParticles(locCombo->Get_SourceParticles(true), Unknown); //all pids
211 std::sort(locParticles.begin(), locParticles.end());
212 auto locUniqueIterator = std::unique(locParticles.begin(), locParticles.end());
213 return (locUniqueIterator != locParticles.end());
214 }
215};
216
217/*********************************************************** INLINE MEMBER FUNCTION DEFINITIONS ************************************************************/
218
219inline DSourceComboInfo::DSourceComboInfo(const vector<pair<Particle_t, unsigned char>>& locNumParticles, const vector<pair<DSourceComboUse, unsigned char>>& locFurtherDecays) :
220 dNumParticles(locNumParticles), dFurtherDecays(locFurtherDecays)
221{
222 std::sort(dNumParticles.begin(), dNumParticles.end(), DCompare_ParticlePairPIDs());
223 std::sort(dFurtherDecays.begin(), dFurtherDecays.end(), DCompare_FurtherDecays());
224}
225
226inline bool DSourceComboInfo::operator< (const DSourceComboInfo& rhs) const
227{
228 if(dNumParticles != rhs.dNumParticles)
229 return dNumParticles < rhs.dNumParticles;
230
231 //check if maps have different sizes
232 if(dFurtherDecays.size() != rhs.dFurtherDecays.size())
233 return dFurtherDecays.size() < rhs.dFurtherDecays.size();
234
235 //check if there's a mismatch between the maps
236 auto locMismachIterators = std::mismatch(dFurtherDecays.begin(), dFurtherDecays.end(), rhs.dFurtherDecays.begin());
237 if(locMismachIterators.first == dFurtherDecays.end())
238 return false; //maps are identical
239
240 //check if keys are equal
241 if(locMismachIterators.first->first == locMismachIterators.second->first)
242 return locMismachIterators.first->second < locMismachIterators.second->second; //compare values
243 else
244 return locMismachIterators.first->first < locMismachIterators.second->first; //compare keys
245}
246
247inline vector<pair<Particle_t, unsigned char>> DSourceComboInfo::Get_NumParticles(bool locEntireChainFlag) const
248{
249 if(!locEntireChainFlag || dFurtherDecays.empty())
250 return dNumParticles;
251
252 vector<pair<Particle_t, unsigned char>> locToReturnNumParticles = dNumParticles;
253 for(const auto& locDecayPair : dFurtherDecays)
254 {
255 const auto& locDecayComboInfo = std::get<2>(locDecayPair.first);
256 auto locNumDecayParticles = locDecayComboInfo->Get_NumParticles(true);
257
258 for(const auto& locParticlePair : locNumDecayParticles)
259 {
260 //search through locToReturnNumParticles to retrieve the iterator corresponding to this PID if it's already present
261 auto locIteratorPair = std::equal_range(locToReturnNumParticles.begin(), locToReturnNumParticles.end(), locParticlePair.first, DCompare_ParticlePairPIDs());
262 if(locIteratorPair.first != locIteratorPair.second)
263 (*locIteratorPair.first).second += locParticlePair.second; //it exists: increase it
264 else //doesn't exist. insert it
265 locToReturnNumParticles.insert(locIteratorPair.first, locParticlePair);
266 }
267 }
268
269 return locToReturnNumParticles;
270}
271
272inline DSourceCombo::DSourceCombo(const vector<pair<Particle_t, const JObject*>>& locSourceParticles, const DSourceCombosByUse_Small& locFurtherDecayCombos, bool locIsZIndependent) :
273 dSourceParticles(locSourceParticles), dFurtherDecayCombos(locFurtherDecayCombos), dIsComboingZIndependent(locIsZIndependent) {}
274
275inline void DSourceCombo::Reset(void)
276{
277 dSourceParticles.clear();
278 dFurtherDecayCombos.clear();
279 dIsComboingZIndependent = false;
280}
281
282inline void DSourceCombo::Set_Members(const vector<pair<Particle_t, const JObject*>>& locSourceParticles, const DSourceCombosByUse_Small& locFurtherDecayCombos, bool locIsZIndependent)
283{
284 dIsComboingZIndependent = locIsZIndependent;
285 dSourceParticles = locSourceParticles;
286 dFurtherDecayCombos = locFurtherDecayCombos;
287 std::sort(dFurtherDecayCombos.begin(), dFurtherDecayCombos.end(), DCompare_FurtherDecays());
288}
289
290inline vector<pair<Particle_t, const JObject*>> DSourceCombo::Get_SourceParticles(bool locEntireChainFlag, Charge_t locCharge) const
291{
292 vector<pair<Particle_t, const JObject*>> locToReturnParticles = dSourceParticles;
293
294 auto Charge_Checker = [&locCharge](const pair<Particle_t, const JObject*>& locPair) -> bool {return !Is_CorrectCharge(locPair.first, locCharge);};
295 locToReturnParticles.erase(std::remove_if(locToReturnParticles.begin(), locToReturnParticles.end(), Charge_Checker), locToReturnParticles.end());
296
297 if(!locEntireChainFlag || dFurtherDecayCombos.empty())
298 return locToReturnParticles;
299
300 for(const auto& locDecayPair : dFurtherDecayCombos)
301 {
302 const auto& locDecayVector = locDecayPair.second;
303 for(const auto& locDecayCombo : locDecayVector)
304 {
305 auto locDecayParticles = locDecayCombo->Get_SourceParticles(true, locCharge);
306 locToReturnParticles.insert(locToReturnParticles.end(), locDecayParticles.begin(), locDecayParticles.end());
307 }
308 }
309
310 return locToReturnParticles;
311}
312
313/*********************************************************** INLINE NAMESPACE FUNCTION DEFINITIONS ************************************************************/
314
315void Print_SourceComboUse(const DSourceComboUse& locComboUse, unsigned char locNumTabs = 0, bool locIgnoreTabs = false);
316inline void Print_SourceComboInfo(const DSourceComboInfo* locComboInfo, unsigned char locNumTabs = 0)
317{
318 if(locComboInfo == nullptr)
319 return;
320
321 auto locNumParticles = locComboInfo->Get_NumParticles(false);
322 for(decltype(locNumTabs) locTabNum = 0; locTabNum < locNumTabs; ++locTabNum) cout << "\t";
323 cout << "Particles: ";
324 for(auto& locParticlePair : locNumParticles)
325 cout << int(locParticlePair.second) << " " << ParticleType(locParticlePair.first) << ", ";
326 cout << endl;
327
328 auto locFurtherDecays = locComboInfo->Get_FurtherDecays();
329 for(auto& locDecayPair : locFurtherDecays)
330 {
331 for(decltype(locNumTabs) locTabNum = 0; locTabNum < locNumTabs; ++locTabNum) cout << "\t";
332 cout << int(locDecayPair.second) << " of ";
333 DAnalysis::Print_SourceComboUse(locDecayPair.first, locNumTabs, true);
334 }
335}
336
337inline void Print_SourceComboUse(const DSourceComboUse& locComboUse, unsigned char locNumTabs, bool locIgnoreTabs)
338{
339 if(!locIgnoreTabs)
340 for(decltype(locNumTabs) locTabNum = 0; locTabNum < locNumTabs; ++locTabNum) cout << "\t";
341 cout << "Use (decay pid, z-bin, combo info, has-missing-decay-product, mass-cut-pid-to-exclude): ";
342 cout << ParticleType(std::get<0>(locComboUse)) << ", " << int(std::get<1>(locComboUse)) << ", " << std::get<2>(locComboUse) << ", " << std::get<3>(locComboUse) << ", " << std::get<4>(locComboUse) << ":" << endl;
343 DAnalysis::Print_SourceComboInfo(std::get<2>(locComboUse), locNumTabs + 1);
344}
345
346inline void Print_SourceCombo(const DSourceCombo* locCombo, unsigned char locNumTabs = 0)
347{
348 if(locCombo == nullptr)
349 return;
350
351 for(decltype(locNumTabs) locTabNum = 0; locTabNum < locNumTabs; ++locTabNum) cout << "\t";
352 cout << "pointer: " << locCombo << ", Z-independent?: " << locCombo->Get_IsComboingZIndependent() << ", Particles: ";
353 auto locSourceParticles = locCombo->Get_SourceParticles();
354 for(auto& locParticlePair : locSourceParticles)
355 cout << ParticleType(locParticlePair.first) << " " << locParticlePair.second << ", ";
356 cout << endl;
357
358 DSourceCombosByUse_Small locFurtherDecayCombos = locCombo->Get_FurtherDecayCombos();
359 for(auto& locDecayPair : locFurtherDecayCombos)
360 {
361 for(decltype(locNumTabs) locTabNum = 0; locTabNum < locNumTabs; ++locTabNum) cout << "\t";
362 cout << locDecayPair.second.size() << " of ";
363 DAnalysis::Print_SourceComboUse(locDecayPair.first, locNumTabs, true);
364 for(auto& locCombo : locDecayPair.second)
365 DAnalysis::Print_SourceCombo(locCombo, locNumTabs + 1);
366 }
367}
368
369inline vector<const JObject*> Get_SourceParticles(const vector<pair<Particle_t, const JObject*>>& locSourceParticles, Particle_t locPID)
370{
371 //if PID is unknown, then all particles
372 vector<const JObject*> locOutputParticles;
373 for(const auto& locParticlePair : locSourceParticles)
374 {
375 if((locPID == Unknown) || (locParticlePair.first == locPID))
376 locOutputParticles.push_back(locParticlePair.second);
377 }
378 return locOutputParticles;
379}
380
381inline vector<const JObject*> Get_SourceParticles(const vector<pair<Particle_t, const JObject*>>& locSourceParticles, int locCharge)
382{
383 //ignores the charge magnitude and sign: only considers if ==/!= 0
384 vector<const JObject*> locOutputParticles;
385 for(const auto& locParticlePair : locSourceParticles)
386 {
387 auto locParticleCharge = ParticleCharge(locParticlePair.first);
388 if((locParticleCharge == locCharge) && (locParticleCharge == 0))
389 locOutputParticles.push_back(locParticlePair.second);
390 else if(locParticleCharge*locCharge != 0)
391 locOutputParticles.push_back(locParticlePair.second);
392 }
393 return locOutputParticles;
394}
395
396inline vector<pair<Particle_t, const JObject*>> Get_SourceParticles_ThisVertex(const DSourceCombo* locSourceCombo, Charge_t locCharge)
397{
398 auto locSourceParticles = locSourceCombo->Get_SourceParticles(false, locCharge);
399 auto locFurtherDecayCombos = locSourceCombo->Get_FurtherDecayCombos();
400 for(const auto& locDecayPair : locFurtherDecayCombos)
401 {
402 auto locDecayPID = std::get<0>(locDecayPair.first);
403 if(IsDetachedVertex(locDecayPID))
404 continue;
405 for(const auto& locDecayCombo : locDecayPair.second)
406 {
407 auto locDecayParticles = Get_SourceParticles_ThisVertex(locDecayCombo, locCharge);
408 locSourceParticles.insert(locSourceParticles.end(), locDecayParticles.begin(), locDecayParticles.end());
409 }
410 }
411
412 return locSourceParticles;
413}
414
415inline vector<const DSourceCombo*> Get_SourceCombos_ThisVertex(const DSourceCombo* locSourceCombo)
416{
417 vector<const DSourceCombo*> locVertexCombos = {locSourceCombo};
418 for(const auto& locDecayPair : locSourceCombo->Get_FurtherDecayCombos())
419 {
420 auto locDecayPID = std::get<0>(locDecayPair.first);
421 if(IsDetachedVertex(locDecayPID))
422 continue;
423 for(const auto& locDecayCombo : locDecayPair.second)
424 {
425 auto locDecayVertexCombos = Get_SourceCombos_ThisVertex(locDecayCombo);
426 locVertexCombos.insert(locVertexCombos.end(), locDecayVertexCombos.begin(), locDecayVertexCombos.end());
427 }
428 }
429 return locVertexCombos;
430}
431
432inline vector<pair<DSourceComboUse, vector<const DSourceCombo*>>> Get_SourceCombosAndUses_ThisVertex(const DSourceCombo* locSourceCombo)
433{
434 //sorted from most- to least-dependent
435 vector<pair<DSourceComboUse, vector<const DSourceCombo*>>> locVertexCombosByUse;
436 for(const auto& locDecayPair : locSourceCombo->Get_FurtherDecayCombos())
437 {
438 auto locDecayPID = std::get<0>(locDecayPair.first);
439 if(IsDetachedVertex(locDecayPID))
440 continue;
441 locVertexCombosByUse.emplace_back(locDecayPair);
442 for(const auto& locDecayCombo : locDecayPair.second)
443 {
444 auto locDecayVertexCombosByUse = Get_SourceCombosAndUses_ThisVertex(locDecayCombo);
445 locVertexCombosByUse.insert(locVertexCombosByUse.end(), locDecayVertexCombosByUse.begin(), locDecayVertexCombosByUse.end());
446 }
447 }
448 return locVertexCombosByUse;
449}
450
451inline Charge_t Get_ChargeContent(const vector<pair<Particle_t, unsigned char>>& locNumParticles)
452{
453 Charge_t locCharge = d_Charged;
454 auto Charge_Search = [&locCharge](const pair<Particle_t, unsigned char>& locPair) -> bool
455 {return Is_CorrectCharge(locPair.first, locCharge);};
456
457 if(!std::any_of(locNumParticles.begin(), locNumParticles.end(), Charge_Search))
458 return d_Neutral;
459
460 locCharge = d_Neutral;
Value stored to 'locCharge' is never read
461 if(!std::any_of(locNumParticles.begin(), locNumParticles.end(), Charge_Search))
462 return d_Charged;
463
464 return d_AllCharges;
465}
466
467inline Charge_t Get_ChargeContent(const DSourceComboInfo* locSourceComboInfo)
468{
469 return Get_ChargeContent(locSourceComboInfo->Get_NumParticles(true));
470}
471
472inline vector<pair<Particle_t, unsigned char>> Get_NumParticles_ThisVertex(const DSourceComboInfo* locSourceComboInfo)
473{
474 //return is NOT sorted
475
476 auto locNumParticles = locSourceComboInfo->Get_NumParticles(false); //only this info, for starters
477 for(const auto& locDecayPair : locSourceComboInfo->Get_FurtherDecays())
478 {
479 auto locDecayPID = std::get<0>(locDecayPair.first);
480 if(IsDetachedVertex(locDecayPID))
481 continue;
482
483 auto locDecayNumParticles = Get_NumParticles_ThisVertex(std::get<2>(locDecayPair.first));
484 for(const auto& locDecayParticlePair : locDecayNumParticles)
485 {
486 bool locFoundFlag = false;
487 for(auto& locParticlePairSoFar : locNumParticles)
488 {
489 if(locDecayParticlePair.first != locParticlePairSoFar.first)
490 continue;
491 locParticlePairSoFar.second += locDecayParticlePair.second;
492 locFoundFlag = true;
493 break;
494 }
495 if(!locFoundFlag)
496 locNumParticles.push_back(locDecayParticlePair);
497 }
498 }
499
500 return locNumParticles;
501}
502
503inline Charge_t Get_ChargeContent_ThisVertex(const DSourceComboInfo* locSourceComboInfo)
504{
505 return Get_ChargeContent(Get_NumParticles_ThisVertex(locSourceComboInfo));
506}
507
508inline bool Get_HasMassiveNeutrals(const DSourceComboInfo* locComboInfo)
509{
510 //see if the combo info contains a massive neutral particle
511
512 //search function
513 auto Find_MassiveNeutrals = [](const pair<Particle_t, unsigned char>& locPair) -> bool
514 {return ((ParticleCharge(locPair.first) == 0) && (ParticleMass(locPair.first) > 0.0));};
515
516 //do search
517 auto locNumParticles = locComboInfo->Get_NumParticles(true); //true: entire chain
518 return std::any_of(locNumParticles.begin(), locNumParticles.end(), Find_MassiveNeutrals);
519}
520
521inline bool Get_HasPhotons(const DSourceComboInfo* locComboInfo)
522{
523 //see if the combo info contains a massive neutral particle
524
525 //search function
526 auto Find_MassiveNeutrals = [](const pair<Particle_t, unsigned char>& locPair) -> bool
527 {return ((ParticleCharge(locPair.first) == 0) && (ParticleMass(locPair.first) <= 0.0000000001));};
528
529 //do search
530 auto locNumParticles = locComboInfo->Get_NumParticles(true); //true: entire chain
531 return std::any_of(locNumParticles.begin(), locNumParticles.end(), Find_MassiveNeutrals);
532}
533
534inline const JObject* Get_SourceParticle_ThisStep(const DSourceCombo* locSourceCombo, Particle_t locPID, size_t locInstance, size_t& locPIDCountSoFar)
535{
536 auto ParticleFinder = [&locPID, &locInstance, &locPIDCountSoFar](pair<Particle_t, const JObject*>& locPair) -> bool
537 {return ((locPair.first != locPID) ? false : ((++locPIDCountSoFar == locInstance) ? true : false));};
538
539 auto locParticles = locSourceCombo->Get_SourceParticles();
540 auto locIterator = std::find_if(locParticles.begin(), locParticles.end(), ParticleFinder);
541 if(locIterator != locParticles.end())
542 return locIterator->second;
543
544 for(const auto& locDecayPair : locSourceCombo->Get_FurtherDecayCombos())
545 {
546 if(std::get<0>(locDecayPair.first) != Unknown)
547 continue; //a new step!
548 for(const auto& locDecayCombo : locDecayPair.second)
549 {
550 auto locParticle = Get_SourceParticle_ThisStep(locDecayCombo, locPID, locInstance, locPIDCountSoFar);
551 if(locParticle != nullptr)
552 return locParticle;
553 }
554 }
555
556 return nullptr;
557}
558
559inline bool Check_AreDuplicateCombos(const DSourceCombo* lhs, const DSourceCombo* rhs)
560{
561 //Assumes inputs are from the same source (excluding z)
562 auto locParticles_lhs = lhs->Get_SourceParticles(false);
563 auto locParticles_rhs = rhs->Get_SourceParticles(false);
564 if(locParticles_lhs.size() != locParticles_rhs.size())
565 return false;
566 if(!std::is_permutation(locParticles_lhs.begin(), locParticles_lhs.end(), locParticles_rhs.begin()))
567 return false;
568
569 auto locDecayCombos_lhs = lhs->Get_FurtherDecayCombos();
570 auto locDecayCombos_rhs = rhs->Get_FurtherDecayCombos();
571 if(locDecayCombos_lhs.size() != locDecayCombos_rhs.size())
572 return false;
573
574 for(auto& locDecayPair : locDecayCombos_lhs)
575 {
576 auto locIteratorPair = std::equal_range(locDecayCombos_rhs.begin(), locDecayCombos_rhs.end(), locDecayPair.first, DSourceCombo::DCompare_FurtherDecays());
577 if(locIteratorPair.first == locIteratorPair.second)
578 return false; //careful, compares z's!!
579
580 auto& locDecayCombos_lhs = locDecayPair.second;
581 auto& locDecayCombos_rhs = (*locIteratorPair.first).second;
582 if(locDecayCombos_lhs.size() != locDecayCombos_rhs.size())
583 return false;
584 if(!std::is_permutation(locDecayCombos_lhs.begin(), locDecayCombos_lhs.end(), locDecayCombos_rhs.begin(), Check_AreDuplicateCombos))
585 return false;
586 }
587 return true;
588}
589
590} //end DAnalysis namespace
591
592#endif // DSourceCombo_h