ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
track_generator_options.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 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 https://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11// Project include(s)
12#include "detray/definitions/algebra.hpp"
13#include "detray/utils/logging.hpp"
14
15// Detray test include(s)
16#include "detray/options/options_handling.hpp"
17#include "detray/test/common/event_generator/random_track_generator_config.hpp"
18#include "detray/test/common/event_generator/uniform_track_generator_config.hpp"
19
20// Boost
21#include "detray/options/boost_program_options.hpp"
22
23// System include(s)
24#include <stdexcept>
25#include <vector>
26
27namespace detray::options {
28
29namespace detail {
30
32template <concepts::scalar scalar_t>
33void add_uniform_track_gen_options(
34 boost::program_options::options_description &desc,
35 const uniform_track_generator_config<scalar_t> &cfg) {
36 desc.add_options()(
37 "phi_steps",
38 boost::program_options::value<std::size_t>()->default_value(
39 cfg.phi_steps()),
40 "No. phi steps for particle gun")(
41 "eta_steps",
42 boost::program_options::value<std::size_t>()->default_value(
43 cfg.eta_steps()),
44 "No. eta steps for particle gun")(
45 "random_seed",
46 boost::program_options::value<std::size_t>()->default_value(cfg.seed()),
47 "Seed for the random number generator")(
48 "eta_range",
49 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
50 "Min, Max range of eta values for particle gun")(
51 "randomize_charge", "Randomly flip charge sign per track")(
52 "origin",
53 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
54 "Coordinates for particle gun origin position [mm]")(
55 "p_range",
56 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
57 "Total momentum [range] of the test particles [GeV]")(
58 "pT_range",
59 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
60 "Transverse momentum [range] of the test particles [GeV]");
61}
62
64template <concepts::scalar scalar_t>
65void configure_uniform_track_gen_options(
66 const boost::program_options::variables_map &vm,
67 uniform_track_generator_config<scalar_t> &cfg) {
68 cfg.phi_steps(vm["phi_steps"].as<std::size_t>());
69 cfg.eta_steps(vm["eta_steps"].as<std::size_t>());
70 cfg.seed(vm["random_seed"].as<std::size_t>());
71 cfg.randomize_charge(vm.count("randomize_charge"));
72
73 if (vm.count("eta_range") != 0u) {
74 const auto eta_range = vm["eta_range"].as<std::vector<scalar_t>>();
75 if (eta_range.size() == 2u) {
76 cfg.eta_range(eta_range[0], eta_range[1]);
77 } else {
78 throw std::invalid_argument("Eta range needs two arguments");
79 }
80 }
81 if (vm.count("origin") != 0u) {
82 const auto origin = vm["origin"].as<std::vector<scalar_t>>();
83 if (origin.size() == 3u) {
84 cfg.origin(origin[0] * unit<scalar_t>::mm, origin[1] * unit<scalar_t>::mm,
85 origin[2] * unit<scalar_t>::mm);
86 } else {
87 throw std::invalid_argument("Particle gun origin needs three arguments");
88 }
89 }
90 if (vm.count("pT_range") != 0u && vm.count("p_range") != 0u) {
91 throw std::invalid_argument(
92 "Transverse and total momentum cannot be specified at the same "
93 "time");
94 }
95 if (vm.count("pT_range") != 0u) {
96 const auto pt_range = vm["pT_range"].as<std::vector<scalar_t>>();
97
98 // Default
99 if (pt_range.empty()) {
100 cfg.p_T(static_cast<scalar_t>(cfg.m_p_mag));
101 } else if (pt_range.size() <= 2u) {
102 if (pt_range.size() == 2u) {
103 DETRAY_ERROR_HOST(
104 "Momentum range not possible with uniform "
105 "track generator: Using first value.");
106 }
107 cfg.p_T(pt_range[0] * unit<scalar_t>::GeV);
108 } else {
109 throw std::invalid_argument(
110 "Wrong number of arguments for pT range: Need one argument or "
111 "range");
112 }
113 } else {
114 auto p_range = std::vector<scalar_t>{};
115 if (vm.count("pT_range") != 0u) {
116 p_range = vm["p_range"].as<std::vector<scalar_t>>();
117 }
118
119 // Default
120 if (p_range.empty()) {
121 cfg.p_tot(static_cast<scalar_t>(cfg.m_p_mag));
122 } else if (p_range.size() <= 2u) {
123 if (p_range.size() == 2u) {
124 DETRAY_ERROR_HOST(
125 "Momentum range not possible with uniform "
126 "track generator: Using first value.");
127 }
128 cfg.p_tot(p_range[0] * unit<scalar_t>::GeV);
129 } else {
130 std::string err_str{
131 "Wrong number of arguments for p_tot range: Need one argument "
132 "or range"};
133 DETRAY_FATAL_HOST(err_str);
134 throw std::invalid_argument(err_str);
135 }
136 }
137}
138
140template <concepts::scalar scalar_t>
141void add_rnd_track_gen_options(
142 boost::program_options::options_description &desc,
143 const random_track_generator_config<scalar_t> &cfg) {
144 desc.add_options()(
145 "n_tracks",
146 boost::program_options::value<std::size_t>()->default_value(
147 cfg.n_tracks()),
148 "No. of tracks for particle gun")(
149 "random_seed",
150 boost::program_options::value<std::size_t>()->default_value(cfg.seed()),
151 "Seed for the random number generator")(
152 "theta_range",
153 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
154 "Min, Max range of theta values for particle gun. Interval in [0, pi)")(
155 "eta_range",
156 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
157 "Min, Max range of eta values for particle gun")(
158 "randomize_charge", "Randomly flip charge sign per track")(
159 "origin",
160 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
161 "Coordinates for particle gun origin position [mm]")(
162 "p_range",
163 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
164 "Total momentum [range] of the test particles [GeV]")(
165 "pT_range",
166 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
167 "Transverse momentum [range] of the test particles [GeV]");
168}
169
171template <concepts::scalar scalar_t>
172void configure_rnd_track_gen_options(
173 const boost::program_options::variables_map &vm,
174 random_track_generator_config<scalar_t> &cfg) {
175 cfg.n_tracks(vm["n_tracks"].as<std::size_t>());
176 cfg.seed(vm["random_seed"].as<std::size_t>());
177 cfg.randomize_charge(vm.count("randomize_charge"));
178
179 if (vm.count("eta_range") != 0u && vm.count("theta_range") != 0u) {
180 throw std::invalid_argument(
181 "Eta range and theta range cannot be specified at the same time");
182 } else if (vm.count("eta_range") != 0u) {
183 const auto eta_range = vm["eta_range"].as<std::vector<scalar_t>>();
184 if (eta_range.size() == 2u) {
185 scalar_t min_theta{2.f * std::atan(std::exp(-eta_range[0]))};
186 scalar_t max_theta{2.f * std::atan(std::exp(-eta_range[1]))};
187
188 // Wrap around
189 if (min_theta > max_theta) {
190 scalar_t tmp{min_theta};
191 min_theta = max_theta;
192 max_theta = tmp;
193 }
194
195 cfg.theta_range(min_theta, max_theta);
196 } else {
197 throw std::invalid_argument("Eta range needs two arguments");
198 }
199 } else if (vm.count("theta_range") != 0u) {
200 const auto theta_range = vm["theta_range"].as<std::vector<scalar_t>>();
201 if (theta_range.size() == 2u) {
202 cfg.theta_range(theta_range[0], theta_range[1]);
203 } else {
204 throw std::invalid_argument("Theta range needs two arguments");
205 }
206 }
207 if (vm.count("origin") != 0u) {
208 const auto origin = vm["origin"].as<std::vector<scalar_t>>();
209 if (origin.size() == 3u) {
210 cfg.origin(origin[0] * unit<scalar_t>::mm, origin[1] * unit<scalar_t>::mm,
211 origin[2] * unit<scalar_t>::mm);
212 } else {
213 throw std::invalid_argument(
214 "Particle gun origin needs three coordinates");
215 }
216 }
217 if (vm.count("pT_range") != 0u && vm.count("p_range") != 0u) {
218 throw std::invalid_argument(
219 "Transverse and total momentum cannot be specified at the same "
220 "time");
221 }
222 if (vm.count("pT_range") != 0u) {
223 const auto pt_range = vm["pT_range"].as<std::vector<scalar_t>>();
224
225 // Default
226 if (pt_range.empty()) {
227 cfg.p_T(cfg.mom_range()[0]);
228 } else if (pt_range.size() == 1u) {
229 cfg.p_T(pt_range[0] * unit<scalar_t>::GeV);
230 } else if (pt_range.size() == 2u) {
231 cfg.pT_range(pt_range[0] * unit<scalar_t>::GeV,
232 pt_range[1] * unit<scalar_t>::GeV);
233 } else {
234 throw std::invalid_argument(
235 "Wrong number of arguments for pT range: Need one argument or "
236 "range");
237 }
238 } else {
239 auto p_range = std::vector<scalar_t>();
240 if (vm.count("pT_range") != 0u) {
241 p_range = vm["p_range"].as<std::vector<scalar_t>>();
242 }
243
244 // Default
245 if (p_range.empty()) {
246 cfg.p_tot(cfg.mom_range()[0]);
247 } else if (p_range.size() == 1u) {
248 cfg.p_tot(p_range[0] * unit<scalar_t>::GeV);
249 } else if (p_range.size() == 2u) {
250 cfg.mom_range(p_range[0] * unit<scalar_t>::GeV,
251 p_range[1] * unit<scalar_t>::GeV);
252 } else {
253 throw std::invalid_argument(
254 "Wrong number of arguments for p_tot range: Need one argument "
255 "or range");
256 }
257 }
258}
259
260} // namespace detail
261
264template <>
265void add_options<uniform_track_generator_config<float>>(
266 boost::program_options::options_description &desc,
267 const uniform_track_generator_config<float> &cfg) {
268 detail::add_uniform_track_gen_options(desc, cfg);
269}
270
271template <>
272void add_options<uniform_track_generator_config<double>>(
273 boost::program_options::options_description &desc,
274 const uniform_track_generator_config<double> &cfg) {
275 detail::add_uniform_track_gen_options(desc, cfg);
276}
278
281template <>
282void configure_options<uniform_track_generator_config<float>>(
283 const boost::program_options::variables_map &vm,
284 uniform_track_generator_config<float> &cfg) {
285 detail::configure_uniform_track_gen_options(vm, cfg);
286}
287
288template <>
289void configure_options<uniform_track_generator_config<double>>(
290 const boost::program_options::variables_map &vm,
291 uniform_track_generator_config<double> &cfg) {
292 detail::configure_uniform_track_gen_options(vm, cfg);
293}
295
298template <>
299void add_options<random_track_generator_config<float>>(
300 boost::program_options::options_description &desc,
301 const random_track_generator_config<float> &cfg) {
302 detail::add_rnd_track_gen_options(desc, cfg);
303}
304
305template <>
306void add_options<random_track_generator_config<double>>(
307 boost::program_options::options_description &desc,
308 const random_track_generator_config<double> &cfg) {
309 detail::add_rnd_track_gen_options(desc, cfg);
310}
312
315template <>
316void configure_options<random_track_generator_config<float>>(
317 const boost::program_options::variables_map &vm,
318 random_track_generator_config<float> &cfg) {
319 detail::configure_rnd_track_gen_options(vm, cfg);
320}
321
322template <>
323void configure_options<random_track_generator_config<double>>(
324 const boost::program_options::variables_map &vm,
325 random_track_generator_config<double> &cfg) {
326 detail::configure_rnd_track_gen_options(vm, cfg);
327}
329
330} // namespace detray::options
static constexpr scalar_t mm
Native length unit, the millimetre.
Definition units.hpp:27
static constexpr scalar_t GeV
Native energy unit, the gigaelectronvolt.
Definition units.hpp:81