Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SpacePointMaker.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SpacePointMaker.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020-2022 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 
23 
24 #include <algorithm>
25 #include <functional>
26 #include <iterator>
27 #include <ostream>
28 #include <stdexcept>
29 #include <utility>
30 #include <variant>
31 
34  : IAlgorithm("SpacePointMaker", lvl), m_cfg(std::move(cfg)) {
35  if (m_cfg.inputSourceLinks.empty()) {
36  throw std::invalid_argument("Missing source link input collection");
37  }
38  if (m_cfg.inputMeasurements.empty()) {
39  throw std::invalid_argument("Missing measurement input collection");
40  }
41  if (m_cfg.outputSpacePoints.empty()) {
42  throw std::invalid_argument("Missing space point output collection");
43  }
44  if (not m_cfg.trackingGeometry) {
45  throw std::invalid_argument("Missing tracking geometry");
46  }
47  if (m_cfg.geometrySelection.empty()) {
48  throw std::invalid_argument("Missing space point maker geometry selection");
49  }
50 
54 
55  // ensure geometry selection contains only valid inputs
56  for (const auto& geoId : m_cfg.geometrySelection) {
57  if ((geoId.approach() != 0u) or (geoId.boundary() != 0u) or
58  (geoId.sensitive() != 0u)) {
59  throw std::invalid_argument(
60  "Invalid geometry selection: only volume and layer are allowed to be "
61  "set");
62  }
63  }
64  // remove geometry selection duplicates
65  //
66  // the geometry selections must be mutually exclusive, i.e. if we have a
67  // selection that contains both a volume and a layer within that same volume,
68  // we would create the space points for the layer twice.
69  auto isDuplicate = [](Acts::GeometryIdentifier ref,
71  // code assumes ref < cmp and that only volume and layer can be non-zero
72  // root node always contains everything
73  if (ref.volume() == 0) {
74  return true;
75  }
76  // unequal volumes always means separate hierarchies
77  if (ref.volume() != cmp.volume()) {
78  return false;
79  }
80  // within the same volume hierarchy only consider layers
81  return (ref.layer() == cmp.layer());
82  };
83  auto geoSelBeg = m_cfg.geometrySelection.begin();
84  auto geoSelEnd = m_cfg.geometrySelection.end();
85  // sort geometry selection so the unique filtering works
86  std::sort(geoSelBeg, geoSelEnd);
87  auto geoSelLastUnique = std::unique(geoSelBeg, geoSelEnd, isDuplicate);
88  if (geoSelLastUnique != geoSelEnd) {
89  ACTS_WARNING("Removed " << std::distance(geoSelLastUnique, geoSelEnd)
90  << " geometry selection duplicates");
91  m_cfg.geometrySelection.erase(geoSelLastUnique, geoSelEnd);
92  }
93  ACTS_INFO("Space point geometry selection:");
94  for (const auto& geoId : m_cfg.geometrySelection) {
95  ACTS_INFO(" " << geoId);
96  }
97  auto spBuilderConfig = Acts::SpacePointBuilderConfig();
98  spBuilderConfig.trackingGeometry = m_cfg.trackingGeometry;
99 
100  m_slSurfaceAccessor.emplace(
102  spBuilderConfig.slSurfaceAccessor
103  .connect<&IndexSourceLink::SurfaceAccessor::operator()>(
104  &m_slSurfaceAccessor.value());
105 
106  auto spConstructor =
107  [](const Acts::Vector3& pos, const Acts::Vector2& cov,
108  boost::container::static_vector<Acts::SourceLink, 2> slinks)
109  -> SimSpacePoint {
110  return SimSpacePoint(pos, cov[0], cov[1], std::move(slinks));
111  };
112 
114  spBuilderConfig, spConstructor,
115  Acts::getDefaultLogger("SpacePointBuilder", lvl));
116 }
117 
119  const AlgorithmContext& ctx) const {
120  const auto& sourceLinks = m_inputSourceLinks(ctx);
121  const auto& measurements = m_inputMeasurements(ctx);
122 
123  // TODO Support strip measurements
125 
126  spOpt.paramCovAccessor = [&measurements](Acts::SourceLink slink) {
127  const auto islink = slink.get<IndexSourceLink>();
128  const auto& meas = measurements[islink.index()];
129 
130  return std::visit(
131  [](const auto& measurement) {
132  auto expander = measurement.expander();
133  Acts::BoundVector par = expander * measurement.parameters();
135  expander * measurement.covariance() * expander.transpose();
136  return std::make_pair(par, cov);
137  },
138  meas);
139  };
140 
141  SimSpacePointContainer spacePoints;
142  for (Acts::GeometryIdentifier geoId : m_cfg.geometrySelection) {
143  // select volume/layer depending on what is set in the geometry id
144  auto range = selectLowestNonZeroGeometryObject(sourceLinks, geoId);
145  // groupByModule only works with geometry containers, not with an
146  // arbitrary range. do the equivalent grouping manually
147  auto groupedByModule = makeGroupBy(range, detail::GeometryIdGetter());
148 
149  for (auto [moduleGeoId, moduleSourceLinks] : groupedByModule) {
150  for (auto& sourceLink : moduleSourceLinks) {
151  m_spacePointBuilder.buildSpacePoint(
152  ctx.geoContext, {Acts::SourceLink{sourceLink}}, spOpt,
153  std::back_inserter(spacePoints));
154  }
155  }
156  }
157 
158  spacePoints.shrink_to_fit();
159 
160  ACTS_DEBUG("Created " << spacePoints.size() << " space points");
161  m_outputSpacePoints(ctx, std::move(spacePoints));
162 
164 }