Belle II Software development
RestOfEvent.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <regex>
10#include <analysis/dataobjects/RestOfEvent.h>
11
12#include <framework/datastore/StoreArray.h>
13
14#include <analysis/dataobjects/Particle.h>
15#include <mdst/dataobjects/ECLCluster.h>
16
17using namespace Belle2;
18// New methods:
19void RestOfEvent::addParticles(const std::vector<const Particle*>& particlesToAdd)
20{
21 StoreArray<Particle> allParticles;
22 for (auto* particleToAdd : particlesToAdd) {
23 std::vector<const Particle*> daughters = particleToAdd->getFinalStateDaughters();
24 for (auto* daughter : daughters) {
25 bool toAdd = true;
26 for (auto& myIndex : m_particleIndices) {
27 if (allParticles[myIndex]->isCopyOf(daughter, true)) {
28 toAdd = false;
29 break;
30 }
31 }
32 if (toAdd) {
33 B2DEBUG(10, "\t\tAdding particle with PDG " << daughter->getPDGCode());
34 m_particleIndices.insert(daughter->getArrayIndex());
35 }
36 }
37 }
38}
39
40std::vector<const Particle*> RestOfEvent::getParticles(const std::string& maskName, bool unpackComposite) const
41{
42 std::vector<const Particle*> result;
43 StoreArray<Particle> allParticles;
44 std::set<int> source;
45 if (m_particleIndices.size() == 0) {
46 B2DEBUG(10, "ROE contains no particles, masks are empty too");
47 return result;
48 }
49 if (maskName == RestOfEvent::c_defaultMaskName or maskName.empty()) {
50 // if no mask provided work with internal source
51 source = m_particleIndices;
52 } else {
53 bool maskFound = false;
54 for (auto& mask : m_masks) {
55 if (mask.getName() == maskName) {
56 maskFound = true;
57 source = mask.getParticles();
58 break;
59 }
60 }
61 if (!maskFound) {
62 B2FATAL("No '" << maskName << "' mask defined in current ROE!");
63 }
64 }
65 for (const int index : source) {
66 if ((allParticles[index]->getParticleSource() == Particle::EParticleSourceObject::c_Composite or
67 allParticles[index]->getParticleSource() == Particle::EParticleSourceObject::c_V0) && unpackComposite) {
68 auto fsdaughters = allParticles[index]->getFinalStateDaughters();
69 for (auto* daughter : fsdaughters) {
70 result.push_back(daughter);
71 }
72 continue;
73 }
74 result.push_back(allParticles[index]);
75 }
76 return result;
77}
78
79std::vector<const Particle*> RestOfEvent::getPhotons(const std::string& maskName, bool unpackComposite) const
80{
81 auto particles = getParticles(maskName, unpackComposite);
82 std::vector<const Particle*> photons;
83 for (auto* particle : particles) {
84 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_ECLCluster) {
85 photons.push_back(particle);
86 }
87 }
88 return photons;
89}
90
91std::vector<const Particle*> RestOfEvent::getHadrons(const std::string& maskName, bool unpackComposite) const
92{
93 auto particles = getParticles(maskName, unpackComposite);
94 std::vector<const Particle*> hadrons;
95 for (auto* particle : particles) {
96 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_KLMCluster) {
97 hadrons.push_back(particle);
98 }
99 }
100 return hadrons;
101}
102
103std::vector<const Particle*> RestOfEvent::getChargedParticles(const std::string& maskName, unsigned int pdg,
104 bool unpackComposite) const
105{
106 auto particles = getParticles(maskName, unpackComposite);
107 std::vector<const Particle*> charged;
108 for (auto* particle : particles) {
109 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_Track) {
110 if (pdg == 0 || pdg == abs(particle->getPDGCode())) {
111 charged.push_back(particle);
112 }
113 }
114 }
115 return charged;
116}
117
118
119bool RestOfEvent::hasParticle(const Particle* particle, const std::string& maskName) const
120{
121 if (maskName != RestOfEvent::c_defaultMaskName && !hasMask(maskName) && !maskName.empty()) {
122 B2FATAL("No '" << maskName << "' mask defined in current ROE!");
123 }
124
125 std::vector<const Particle*> particlesROE = getParticles(maskName);
126 return isInParticleList(particle, particlesROE);
127}
128
129void RestOfEvent::initializeMask(const std::string& name, const std::string& origin)
130{
131 if (name == "") {
132 B2FATAL("Creation of ROE Mask with an empty name is not allowed!");
133 }
134 if (name == RestOfEvent::c_defaultMaskName) {
135 B2FATAL("Creation of ROE Mask with a name " << RestOfEvent::c_defaultMaskName << " is not allowed!");
136 }
137 std::regex word_regex("^[a-zA-Z][a-zA-Z0-9_]*$");
138 if (!std::regex_match(name, word_regex)) {
139 B2FATAL("Mask name '" << name << "' contains forbidden characters or it does not start with a letter. "
140 "Only alphanumeric and underscore characters are allowed in ROE mask names.");
141 }
142 if (findMask(name)) {
143 B2FATAL("ROE Mask '" << name << "' already exists!");
144 }
145 Mask elon(name, origin);
146 m_masks.push_back(elon);
147}
148
149void RestOfEvent::excludeParticlesFromMask(const std::string& maskName, const std::vector<const Particle*>& particlesToUpdate,
150 Particle::EParticleSourceObject listType, bool discard)
151{
152 if (maskName == RestOfEvent::c_defaultMaskName) {
153 B2FATAL("ROE Mask name '" << RestOfEvent::c_defaultMaskName << "' is reserved for no mask case! " <<
154 "Please check your inputs.");
155 }
156 Mask* mask = findMask(maskName);
157 if (!mask) {
158 B2FATAL("No '" << maskName << "' mask defined in current ROE!");
159 }
160 std::string maskNameToGetParticles = maskName;
161 if (!mask->isValid()) {
162 maskNameToGetParticles = RestOfEvent::c_defaultMaskName;
163 }
164 std::vector<const Particle*> allROEParticles = getParticles(maskNameToGetParticles);
165 std::vector<const Particle*> toKeepinROE;
166 for (auto* roeParticle : allROEParticles) {
167 if (isInParticleList(roeParticle, particlesToUpdate)) {
168 if (!discard) {
169 // If keep particles option is on, take the equal particles
170 toKeepinROE.push_back(roeParticle);
171 }
172 } else {
173 // Keep all particles which has different type than provided list
174 if (listType != roeParticle->getParticleSource()) {
175 toKeepinROE.push_back(roeParticle);
176 } else if (discard) {
177 // If keep particles option is off, take not equal particles
178 toKeepinROE.push_back(roeParticle);
179 }
180 }
181 }
182 mask->clearParticles();
183 mask->addParticles(toKeepinROE);
184}
185
186void RestOfEvent::updateMaskWithCuts(const std::string& maskName, const std::shared_ptr<Variable::Cut>& trackCut,
187 const std::shared_ptr<Variable::Cut>& eclCut, const std::shared_ptr<Variable::Cut>& klmCut, bool updateExisting)
188{
189 if (maskName == RestOfEvent::c_defaultMaskName) {
190 B2FATAL("ROE Mask name '" << RestOfEvent::c_defaultMaskName << "' is reserved for no mask case! " <<
191 "Please check your inputs.");
192 }
193 Mask* mask = findMask(maskName);
194 if (!mask) {
195 B2FATAL("ROE Mask '" << maskName << "' does not exist!");
196 }
197 std::string sourceName = RestOfEvent::c_defaultMaskName;
198 if (updateExisting) {
199 // if mask already exists, take its particles to update
200 sourceName = maskName;
201 }
202 // get all initial ROE particles, don't touch the possible V0s, otherwise, some daughters may be excluded, and some not... This may be revisited if needed
203 std::vector<const Particle*> allROEParticles = getParticles(sourceName, false);
204 std::vector<const Particle*> maskedParticles;
205 // First check particle type, then check cuts, if no cuts provided, take all particles of this type
206 for (auto* particle : allROEParticles) {
207 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_Track && (!trackCut || trackCut->check(particle))) {
208 maskedParticles.push_back(particle);
209 }
210 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_ECLCluster && (!eclCut || eclCut->check(particle))) {
211 maskedParticles.push_back(particle);
212 }
213 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_KLMCluster && (!klmCut || klmCut->check(particle))) {
214 maskedParticles.push_back(particle);
215 }
216 // don't lose a possible V0 particle
217 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_Composite or
218 particle->getParticleSource() == Particle::EParticleSourceObject::c_V0) {
219 maskedParticles.push_back(particle);
220 }
221 }
222 mask->clearParticles();
223 mask->addParticles(maskedParticles);
224}
225
226void RestOfEvent::updateMaskWithV0(const std::string& name, const Particle* particleV0)
227{
228 if (name == RestOfEvent::c_defaultMaskName) {
229 B2FATAL("ROE Mask name '" << RestOfEvent::c_defaultMaskName << "' is reserved for no mask case! " <<
230 "Please check your inputs.");
231 }
232 Mask* mask = findMask(name);
233 if (!mask) {
234 B2FATAL("ROE Mask '" << name << "' does not exist!");
235 }
236 std::vector<const Particle*> allROEParticles = getParticles(name, false);
237 std::vector<int> indicesToErase;
238 std::vector<const Particle*> daughtersV0 = particleV0->getFinalStateDaughters();
239 for (auto* maskParticle : allROEParticles) {
240 bool toKeep = true;
241 for (auto* daughterV0 : daughtersV0) {
242 if (daughterV0->isCopyOf(maskParticle, true)) {
243 toKeep = false;
244 }
245 }
246 if (!toKeep) {
247 indicesToErase.push_back(maskParticle->getArrayIndex());
248 }
249 }
250 if (daughtersV0.size() != indicesToErase.size()) {
251 B2DEBUG(10, "Only " << indicesToErase.size() << " daughters are excluded from mask particles. Abort");
252 return;
253 }
254 std::string toprint = "We will erase next indices from " + name + " mask: ";
255 for (auto& i : indicesToErase) {
256 toprint += std::to_string(i) + " ";
257 }
258 B2DEBUG(10, toprint);
259 // If everything is good, we add
260 mask->addV0(particleV0, indicesToErase);
261}
262
263bool RestOfEvent::checkCompatibilityOfMaskAndV0(const std::string& name, const Particle* particleV0)
264{
265 if (name == RestOfEvent::c_defaultMaskName) {
266 B2FATAL("ROE Mask name '" << RestOfEvent::c_defaultMaskName << "' is reserved for no mask case! " <<
267 "Please check your inputs.");
268 }
269 Mask* mask = findMask(name);
270 if (!mask) {
271 B2FATAL("ROE Mask '" << name << "' does not exist!");
272 }
273 if (!mask->isValid()) {
274 return false; //We should have particles here!
275 }
276 if (particleV0->getParticleSource() != Particle::EParticleSourceObject::c_Composite and
277 particleV0->getParticleSource() != Particle::EParticleSourceObject::c_V0) {
278 return false;
279 }
280 std::vector<const Particle*> daughtersV0 = particleV0->getFinalStateDaughters();
281 for (auto* daughter : daughtersV0) {
282 if (daughter->getParticleSource() != Particle::EParticleSourceObject::c_Track) {
283 return false; // Non tracks are not supported yet
284 }
285 }
286 if (mask->hasV0(particleV0)) {
287 return false; // We are not going to add another one
288 }
289 return true;
290}
291
292bool RestOfEvent::hasMask(const std::string& name) const
293{
294 for (auto& mask : m_masks) {
295 if (mask.getName() == name) {
296 return true;
297 }
298 }
299 return false;
300}
301ROOT::Math::PxPyPzEVector RestOfEvent::get4Vector(const std::string& maskName) const
302{
303 ROOT::Math::PxPyPzEVector roe4Vector;
304 std::vector<const Particle*> myParticles = RestOfEvent::getParticles(maskName);
305 for (const Particle* particle : myParticles) {
306 // KLMClusters are discarded, because KLM energy estimation is based on hit numbers, therefore it is unreliable
307 // also, enable it as an experimental option:
308 if (particle->getParticleSource() == Particle::EParticleSourceObject::c_KLMCluster and !m_useKLMEnergy) {
309 continue;
310 }
311 roe4Vector += particle->get4Vector();
312 }
313 return roe4Vector;
314}
315
316
318{
319 for (auto& mask : m_masks) {
320 if (mask.getName() == name) {
321 return &mask;
322 }
323 }
324 return nullptr;
325
326}
327
328int RestOfEvent::getNTracks(const std::string& maskName) const
329{
330 int nTracks = getChargedParticles(maskName).size();
331 return nTracks;
332}
333
334int RestOfEvent::getNECLClusters(const std::string& maskName) const
335{
336 int nROEneutralECLClusters = getPhotons(maskName).size();
337 int nROEchargedECLClusters = 0;
338 for (auto& roeParticle : getChargedParticles(maskName)) {
339 if (roeParticle->getECLCluster()) ++nROEchargedECLClusters;
340 }
341
342 return nROEneutralECLClusters + nROEchargedECLClusters;
343}
344
345int RestOfEvent::getNKLMClusters(const std::string& maskName) const
346{
347 int nROEKLMClusters = getHadrons(maskName).size();
348 return nROEKLMClusters;
349}
350
351ROOT::Math::PxPyPzEVector RestOfEvent::get4VectorNeutralECLClusters(const std::string& maskName) const
352{
353 auto roeClusters = getPhotons(maskName);
354 ROOT::Math::PxPyPzEVector roe4VectorECLClusters;
355
356 // Add all momenta from neutral ECLClusters which have the nPhotons hypothesis
357 for (auto& roeCluster : roeClusters) {
358 if (roeCluster->getECLClusterEHypothesisBit() == ECLCluster::EHypothesisBit::c_nPhotons)
359 roe4VectorECLClusters += roeCluster->get4Vector();
360 }
361
362 return roe4VectorECLClusters;
363}
364
365bool RestOfEvent::isInParticleList(const Particle* roeParticle, const std::vector<const Particle*>& particlesToUpdate) const
366{
367 for (auto* listParticle : particlesToUpdate) {
368 if (roeParticle->isCopyOf(listParticle, true)) {
369 return true;
370 }
371 }
372 return false;
373}
374
375std::vector<std::string> RestOfEvent::getMaskNames() const
376{
377 std::vector<std::string> maskNames;
378
379 for (auto& mask : m_masks) {
380 maskNames.push_back(mask.getName());
381 }
382
383 return maskNames;
384}
385
386void RestOfEvent::print(const std::string& maskName, bool unpackComposite) const
387{
388 std::string tab = " - ";
389 if (maskName != RestOfEvent::c_defaultMaskName) {
390 // Disable possible B2FATAL in printing method, might be useful for tests
391 if (!hasMask(maskName)) {
392 B2WARNING("No mask with the name '" << maskName << "' exists in this ROE! Nothing else to print");
393 return;
394 }
395 tab = " - - ";
396 } else {
397 if (m_isNested) {
398 B2INFO(tab << "ROE is nested");
399 }
400 if (m_isFromMC) {
401 B2INFO(tab << "ROE is build from generated particles");
402 }
403 }
404 if (m_useKLMEnergy) {
405 B2WARNING("This ROE has KLM energy included into its 4-vector!");
406 }
407 if (!m_isFromMC) {
408 unsigned int nCharged = getChargedParticles(maskName, 0, unpackComposite).size();
409 unsigned int nPhotons = getPhotons(maskName, unpackComposite).size();
410 unsigned int nNeutralHadrons = getHadrons(maskName, unpackComposite).size();
411 B2INFO(tab << "No. of Charged particles in ROE: " << nCharged);
412 B2INFO(tab << "No. of Photons in ROE: " << nPhotons);
413 B2INFO(tab << "No. of K_L0 and neutrons in ROE: " << nNeutralHadrons);
414 } else {
415 unsigned int nParticles = getParticles(maskName, unpackComposite).size();
416 B2INFO(tab << "No. of generated particles in ROE: " << nParticles);
417 }
418 printIndices(maskName, unpackComposite, tab);
419}
420
421void RestOfEvent::printIndices(const std::string& maskName, bool unpackComposite, const std::string& tab) const
422{
423 auto particles = getParticles(maskName, unpackComposite);
424 if (particles.size() == 0) {
425 B2INFO(tab << "No indices to print");
426 return;
427 }
428 std::string printoutIndex = tab + "|";
429 std::string printoutPDG = tab + "|";
430 for (const auto particle : particles) {
431 printoutIndex += std::to_string(particle->getArrayIndex()) + " | ";
432 printoutPDG += std::to_string(particle->getPDGCode()) + " | ";
433 }
434 B2INFO(printoutPDG);
435 B2INFO(printoutIndex);
436}
437
438Particle* RestOfEvent::convertToParticle(const std::string& maskName, int pdgCode, bool isSelfConjugated)
439{
440 StoreArray<Particle> particles;
441 std::set<int> source;
442 if (maskName == RestOfEvent::c_defaultMaskName) {
443 // if no mask provided work with internal source
444 source = m_particleIndices;
445 } else {
446 bool maskFound = false;
447 for (auto& mask : m_masks) {
448 if (mask.getName() == maskName) {
449 maskFound = true;
450 source = mask.getParticles();
451 break;
452 }
453 }
454 if (!maskFound) {
455 B2FATAL("No '" << maskName << "' mask defined in current ROE!");
456 }
457 }
458 int particlePDG = (pdgCode == 0) ? getPDGCode() : pdgCode;
459 auto isFlavored = (isSelfConjugated) ? Particle::EFlavorType::c_Unflavored : Particle::EFlavorType::c_Flavored;
460 // By default, the ROE-based particles should have unspecified property to simplify the MC-matching
462 // Same properties as for "->" usage in DecayDescriptor
465 return particles.appendNew(get4Vector(maskName), particlePDG, isFlavored, std::vector(source.begin(),
466 source.end()), propertyFlags);
467}
468
@ c_nPhotons
CR is split into n photons (N1)
Class to store reconstructed particles.
Definition: Particle.h:76
std::vector< const Belle2::Particle * > getFinalStateDaughters() const
Returns a vector of pointers to Final State daughter particles.
Definition: Particle.cc:680
EParticleSourceObject
particle source enumerators
Definition: Particle.h:83
bool isCopyOf(const Particle *oParticle, bool doDetailedComparison=false) const
Returns true if this Particle and oParticle are copies of each other.
Definition: Particle.cc:783
EParticleSourceObject getParticleSource() const
Returns particle source as defined with enum EParticleSourceObject.
Definition: Particle.h:489
@ c_Unflavored
Is its own antiparticle or we don't know whether it is a particle/antiparticle.
Definition: Particle.h:97
@ c_Flavored
Is either particle or antiparticle.
Definition: Particle.h:98
@ c_IsIgnoreRadiatedPhotons
Is the particle MC matched with the ignore radiated photon flag set?
Definition: Particle.h:121
@ c_IsUnspecified
Ordinary particles.
Definition: Particle.h:120
@ c_IsIgnoreIntermediate
Is the particle MC matched with the ignore intermediate resonances flag set?
Definition: Particle.h:122
ROOT::Math::PxPyPzEVector get4Vector(const std::string &maskName=c_defaultMaskName) const
Get 4-momentum vector all (no mask) or a subset (use mask) of all Tracks and ECLClusters in ROE.
Definition: RestOfEvent.cc:301
int getPDGCode() const
Gets the PDG code of the rest of event.
Definition: RestOfEvent.h:211
int getNECLClusters(const std::string &maskName=c_defaultMaskName) const
Get number of all (no mask) or a subset (use mask) of all ECLclusters in ROE.
Definition: RestOfEvent.cc:334
std::set< int > m_particleIndices
StoreArray indices to unused particles.
Definition: RestOfEvent.h:362
std::vector< const Particle * > getParticles(const std::string &maskName=c_defaultMaskName, bool unpackComposite=true) const
Get all Particles from ROE mask.
Definition: RestOfEvent.cc:40
std::vector< const Particle * > getChargedParticles(const std::string &maskName=c_defaultMaskName, unsigned int pdg=0, bool unpackComposite=true) const
Get charged particles from ROE mask.
Definition: RestOfEvent.cc:103
void print(const std::string &maskName=c_defaultMaskName, bool unpackComposite=true) const
Prints the contents of a RestOfEvent object to screen.
Definition: RestOfEvent.cc:386
void initializeMask(const std::string &name, const std::string &origin="unknown")
Initialize new mask.
Definition: RestOfEvent.cc:129
bool checkCompatibilityOfMaskAndV0(const std::string &name, const Particle *particleV0)
Check if V0 can be added, maybe should be moved to private.
Definition: RestOfEvent.cc:263
static constexpr const char * c_defaultMaskName
Default mask name.
Definition: RestOfEvent.h:60
ROOT::Math::PxPyPzEVector get4VectorNeutralECLClusters(const std::string &maskName=c_defaultMaskName) const
Get 4-momentum vector all (no mask) or a subset (use mask) of all ECLClusters in ROE.
Definition: RestOfEvent.cc:351
void printIndices(const std::string &maskName=c_defaultMaskName, bool unpackComposite=true, const std::string &tab=" - ") const
Prints indices in the given set in a single line.
Definition: RestOfEvent.cc:421
void updateMaskWithCuts(const std::string &name, const std::shared_ptr< Variable::Cut > &trackCut=nullptr, const std::shared_ptr< Variable::Cut > &eclCut=nullptr, const std::shared_ptr< Variable::Cut > &klmCut=nullptr, bool updateExisting=false)
Update mask with cuts.
Definition: RestOfEvent.cc:186
int getNTracks(const std::string &maskName=c_defaultMaskName) const
Get number of all (no mask) or a subset (use mask) of all Tracks in ROE.
Definition: RestOfEvent.cc:328
bool hasMask(const std::string &name) const
True if this ROE object has mask.
Definition: RestOfEvent.cc:292
std::vector< const Particle * > getPhotons(const std::string &maskName=c_defaultMaskName, bool unpackComposite=true) const
Get photons from ROE mask.
Definition: RestOfEvent.cc:79
bool m_isFromMC
MC ROE indicator.
Definition: RestOfEvent.h:366
bool hasParticle(const Particle *particle, const std::string &maskName=c_defaultMaskName) const
Check if ROE has StoreArray index of given to the list of unused tracks in the event.
Definition: RestOfEvent.cc:119
Mask * findMask(const std::string &name)
Helper method to find ROE mask.
Definition: RestOfEvent.cc:317
Particle * convertToParticle(const std::string &maskName=c_defaultMaskName, int pdgCode=0, bool isSelfConjugated=true)
Converts ROE to Particle and adds it to StoreArray.
Definition: RestOfEvent.cc:438
void addParticles(const std::vector< const Particle * > &particle)
Add StoreArray indices of given Particles to the list of unused particles in the event.
Definition: RestOfEvent.cc:19
int getNKLMClusters(const std::string &maskName=c_defaultMaskName) const
Get number of all remaining KLM clusters.
Definition: RestOfEvent.cc:345
std::vector< std::string > getMaskNames() const
Get vector of all mask names of the ROE object.
Definition: RestOfEvent.cc:375
void updateMaskWithV0(const std::string &name, const Particle *particleV0)
Update mask with composite particle.
Definition: RestOfEvent.cc:226
bool m_useKLMEnergy
Include KLM energy into ROE 4-vector.
Definition: RestOfEvent.h:367
std::vector< const Particle * > getHadrons(const std::string &maskName=c_defaultMaskName, bool unpackComposite=true) const
Get hadrons from ROE mask.
Definition: RestOfEvent.cc:91
std::vector< Mask > m_masks
List of the ROE masks.
Definition: RestOfEvent.h:363
void excludeParticlesFromMask(const std::string &maskName, const std::vector< const Particle * > &particles, Particle::EParticleSourceObject listType, bool discard)
Update mask by keeping or excluding particles.
Definition: RestOfEvent.cc:149
bool isInParticleList(const Particle *roeParticle, const std::vector< const Particle * > &particlesToUpdate) const
Checks if a particle has its copy in the provided list.
Definition: RestOfEvent.cc:365
bool m_isNested
Nested ROE indicator.
Definition: RestOfEvent.h:365
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
Abstract base class for different kinds of events.
Structure of Rest of Event mask.
Definition: RestOfEvent.h:68