Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MeasurementsCreator.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MeasurementsCreator.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 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 
9 #pragma once
10 
21 
22 #include <memory>
23 #include <random>
24 #include <vector>
25 
26 namespace Acts {
27 namespace Test {
28 
30 enum class MeasurementType {
31  eLoc0,
32  eLoc1,
33  eLoc01,
34 };
35 
38  MeasurementType type = MeasurementType::eLoc0;
39  // Depending on the type, only the first value is used.
40  std::array<double, 2> stddev = {50 * UnitConstants::um, 0};
41 };
42 
46 
48 struct Measurements {
49  std::vector<TestSourceLink> sourceLinks;
50  std::vector<TestSourceLink> outlierSourceLinks;
51  std::vector<BoundVector> truthParameters;
52 };
53 
57 
59  std::default_random_engine* rng = nullptr;
60  size_t sourceId = 0;
61  // how far away from the measurements the outliers should be
63 
73  template <typename propagator_state_t, typename stepper_t,
74  typename navigator_t>
75  void operator()(propagator_state_t& state, const stepper_t& stepper,
76  const navigator_t& navigator, result_type& result,
77  const Logger& logger) const {
78  using namespace Acts::UnitLiterals;
79 
80  // only generate measurements on surfaces
81  if (not navigator.currentSurface(state.navigation)) {
82  return;
83  }
84  const Acts::Surface& surface = *navigator.currentSurface(state.navigation);
85  const Acts::GeometryIdentifier geoId = surface.geometryId();
86  // only generate measurements on sensitive surface
87  if (not geoId.sensitive()) {
88  ACTS_VERBOSE("Create no measurements on non-sensitive surface " << geoId);
89  return;
90  }
91  // only generate measurements if a resolution is configured
92  auto found = resolutions.find(geoId);
93  if (found == resolutions.end()) {
94  ACTS_VERBOSE("No resolution configured for sensitive surface " << geoId);
95  return;
96  }
97  const MeasurementResolution& resolution = *found;
98 
99  // Apply global to local
101  surface
102  .globalToLocal(state.geoContext, stepper.position(state.stepping),
103  stepper.direction(state.stepping))
104  .value();
105  // The truth info
106  BoundVector parameters = BoundVector::Zero();
109  const auto& direction = stepper.position(state.stepping);
112  parameters[eBoundQOverP] = state.stepping.pars[eFreeQOverP];
113  parameters[eBoundTime] = state.stepping.pars[eFreeTime];
114  result.truthParameters.push_back(std::move(parameters));
115 
116  std::normal_distribution<double> normalDist(0., 1.);
117 
118  // compute covariance for all components, might contain bogus values
119  // depending on the configuration. but those remain unused.
120  Vector2 stddev(resolution.stddev[0], resolution.stddev[1]);
121  SquareMatrix2 cov = stddev.cwiseProduct(stddev).asDiagonal();
122 
123  if (resolution.type == MeasurementType::eLoc0) {
124  double val = loc[0] + stddev[0] * normalDist(*rng);
125  double out = val + distanceOutlier;
126  result.sourceLinks.emplace_back(eBoundLoc0, val, cov(0, 0), geoId,
127  sourceId);
128  result.outlierSourceLinks.emplace_back(eBoundLoc0, out, cov(0, 0), geoId,
129  sourceId);
130  } else if (resolution.type == MeasurementType::eLoc1) {
131  // yes, using stddev[0] and cov(0,0) is correct here. this accesses the
132  // first configuration parameter not the first local coordinate.
133  double val = loc[1] + stddev[0] * normalDist(*rng);
134  double out = val + distanceOutlier;
135  result.sourceLinks.emplace_back(eBoundLoc1, val, cov(0, 0), geoId,
136  sourceId);
137  result.outlierSourceLinks.emplace_back(eBoundLoc1, out, cov(0, 0), geoId,
138  sourceId);
139  } else if (resolution.type == MeasurementType::eLoc01) {
140  Vector2 val = loc + stddev.cwiseProduct(
141  Vector2(normalDist(*rng), normalDist(*rng)));
143  result.sourceLinks.emplace_back(eBoundLoc0, eBoundLoc1, val, cov, geoId,
144  sourceId);
145  result.outlierSourceLinks.emplace_back(eBoundLoc0, eBoundLoc1, out, cov,
146  geoId, sourceId);
147  }
148  }
149 };
150 
152 template <typename propagator_t, typename track_parameters_t>
156  const track_parameters_t& trackParameters,
158  std::default_random_engine& rng,
159  size_t sourceId = 0u) {
160  using Actions = Acts::ActionList<MeasurementsCreator>;
161  using Aborters = Acts::AbortList<Acts::EndOfWorldReached>;
162 
163  // Set options for propagator
165  auto& creator = options.actionList.get<MeasurementsCreator>();
166  creator.resolutions = resolutions;
167  creator.rng = &rng;
168  creator.sourceId = sourceId;
169 
170  // Launch and collect the measurements
171  auto result = propagator.propagate(trackParameters, options).value();
172  return std::move(result.template get<Measurements>());
173 }
174 
175 } // namespace Test
176 } // namespace Acts