Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ParticleSelector.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ParticleSelector.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019-2020 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
18 
19 #include <ostream>
20 #include <stdexcept>
21 #include <utility>
22 
25  : IAlgorithm("ParticleSelector", level), m_cfg(config) {
26  if (m_cfg.inputParticles.empty()) {
27  throw std::invalid_argument("Missing input particles collection");
28  }
29  if (m_cfg.outputParticles.empty()) {
30  throw std::invalid_argument("Missing output particles collection");
31  }
32 
35 
36  ACTS_DEBUG("selection particle rho [" << m_cfg.rhoMin << "," << m_cfg.rhoMax
37  << ")");
38  ACTS_DEBUG("selection particle |z| [" << m_cfg.absZMin << "," << m_cfg.absZMax
39  << ")");
40  ACTS_DEBUG("selection particle time [" << m_cfg.timeMin << ","
41  << m_cfg.timeMax << ")");
42  ACTS_DEBUG("selection particle phi [" << m_cfg.phiMin << "," << m_cfg.phiMax
43  << ")");
44  ACTS_DEBUG("selection particle eta [" << m_cfg.etaMin << "," << m_cfg.etaMax
45  << ")");
46  ACTS_DEBUG("selection particle |eta| [" << m_cfg.absEtaMin << ","
47  << m_cfg.absEtaMax << ")");
48  ACTS_DEBUG("selection particle pt [" << m_cfg.ptMin << "," << m_cfg.ptMax
49  << ")");
50  ACTS_DEBUG("selection particle m [" << m_cfg.mMin << "," << m_cfg.mMax
51  << ")");
52  ACTS_DEBUG("remove charged particles " << m_cfg.removeCharged);
53  ACTS_DEBUG("remove neutral particles " << m_cfg.removeNeutral);
54  ACTS_DEBUG("remove secondary particles " << m_cfg.removeSecondaries);
55 
56  // We only initialize this if we actually select on this
57  if (m_cfg.measurementsMin > 0 or
58  m_cfg.measurementsMax < std::numeric_limits<std::size_t>::max()) {
60  ACTS_DEBUG("selection particle number of measurements ["
61  << m_cfg.measurementsMin << "," << m_cfg.measurementsMax << ")");
62  }
63 }
64 
66  const AlgorithmContext& ctx) const {
67  using ParticlesMeasurmentMap =
68  boost::container::flat_multimap<ActsFatras::Barcode, Index>;
69 
70  // prepare input/ output types
71  const auto& inputParticles = m_inputParticles(ctx);
72 
73  // Make global particles measurement map if necessary
74  std::optional<ParticlesMeasurmentMap> particlesMeasMap;
75  if (m_inputMap.isInitialized()) {
76  particlesMeasMap = invertIndexMultimap(m_inputMap(ctx));
77  }
78 
79  std::size_t nInvalidCharge = 0;
80  std::size_t nInvalidMeasurementCount = 0;
81 
82  // helper functions to select tracks
83  auto within = [](auto x, auto min, auto max) {
84  return (min <= x) and (x < max);
85  };
86 
87  auto isValidParticle = [&](const ActsFatras::Particle& p) {
88  const auto eta = Acts::VectorHelpers::eta(p.direction());
89  const auto phi = Acts::VectorHelpers::phi(p.direction());
90  const auto rho = Acts::VectorHelpers::perp(p.position());
91  // define charge selection
92  const bool validNeutral = (p.charge() == 0) and not m_cfg.removeNeutral;
93  const bool validCharged = (p.charge() != 0) and not m_cfg.removeCharged;
94  const bool validCharge = validNeutral or validCharged;
95  const bool validSecondary = not m_cfg.removeSecondaries or !p.isSecondary();
96 
97  nInvalidCharge += static_cast<std::size_t>(not validCharge);
98 
99  // default valid measurement count to true and only change if we have loaded
100  // the measurement particles map
101  bool validMeasurementCount = true;
102  if (particlesMeasMap) {
103  auto [b, e] = particlesMeasMap->equal_range(p.particleId());
104  validMeasurementCount =
105  within(static_cast<std::size_t>(std::distance(b, e)),
106  m_cfg.measurementsMin, m_cfg.measurementsMax);
107 
108  ACTS_VERBOSE("Found " << std::distance(b, e) << " measurements for "
109  << p.particleId());
110  }
111 
112  nInvalidMeasurementCount +=
113  static_cast<std::size_t>(not validMeasurementCount);
114 
115  return validCharge and validSecondary and validMeasurementCount and
116  within(p.transverseMomentum(), m_cfg.ptMin, m_cfg.ptMax) and
117  within(std::abs(eta), m_cfg.absEtaMin, m_cfg.absEtaMax) and
118  within(eta, m_cfg.etaMin, m_cfg.etaMax) and
119  within(phi, m_cfg.phiMin, m_cfg.phiMax) and
120  within(std::abs(p.position()[Acts::ePos2]), m_cfg.absZMin,
121  m_cfg.absZMax) and
122  within(rho, m_cfg.rhoMin, m_cfg.rhoMax) and
123  within(p.time(), m_cfg.timeMin, m_cfg.timeMax) and
124  within(p.mass(), m_cfg.mMin, m_cfg.mMax);
125  };
126 
128  outputParticles.reserve(inputParticles.size());
129 
130  // copy selected particles
131  for (const auto& inputParticle : inputParticles) {
132  if (isValidParticle(inputParticle)) {
133  // the input parameters should already be
134  outputParticles.insert(outputParticles.end(), inputParticle);
135  }
136  }
137  outputParticles.shrink_to_fit();
138 
139  ACTS_DEBUG("event " << ctx.eventNumber << " selected "
140  << outputParticles.size() << " from "
141  << inputParticles.size() << " particles");
142  ACTS_DEBUG("filtered out because of charge: " << nInvalidCharge);
143  ACTS_DEBUG("filtered out because of measurement count: "
144  << nInvalidMeasurementCount);
145 
146  m_outputParticles(ctx, std::move(outputParticles));
147  return ProcessCode::SUCCESS;
148 }