File indexing completed on 2026-05-27 07:24:18
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/algebra.hpp"
0013 #include "detray/utils/logging.hpp"
0014
0015
0016 #include "detray/options/options_handling.hpp"
0017 #include "detray/test/common/event_generator/random_track_generator_config.hpp"
0018 #include "detray/test/common/event_generator/uniform_track_generator_config.hpp"
0019
0020
0021 #include "detray/options/boost_program_options.hpp"
0022
0023
0024 #include <stdexcept>
0025 #include <vector>
0026
0027 namespace detray::options {
0028
0029 namespace detail {
0030
0031
0032 template <concepts::scalar scalar_t>
0033 void add_uniform_track_gen_options(
0034 boost::program_options::options_description &desc,
0035 const uniform_track_generator_config<scalar_t> &cfg) {
0036 desc.add_options()(
0037 "phi_steps",
0038 boost::program_options::value<std::size_t>()->default_value(
0039 cfg.phi_steps()),
0040 "No. phi steps for particle gun")(
0041 "eta_steps",
0042 boost::program_options::value<std::size_t>()->default_value(
0043 cfg.eta_steps()),
0044 "No. eta steps for particle gun")(
0045 "random_seed",
0046 boost::program_options::value<std::size_t>()->default_value(cfg.seed()),
0047 "Seed for the random number generator")(
0048 "eta_range",
0049 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0050 "Min, Max range of eta values for particle gun")(
0051 "randomize_charge", "Randomly flip charge sign per track")(
0052 "origin",
0053 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0054 "Coordinates for particle gun origin position [mm]")(
0055 "p_range",
0056 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0057 "Total momentum [range] of the test particles [GeV]")(
0058 "pT_range",
0059 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0060 "Transverse momentum [range] of the test particles [GeV]");
0061 }
0062
0063
0064 template <concepts::scalar scalar_t>
0065 void configure_uniform_track_gen_options(
0066 const boost::program_options::variables_map &vm,
0067 uniform_track_generator_config<scalar_t> &cfg) {
0068 cfg.phi_steps(vm["phi_steps"].as<std::size_t>());
0069 cfg.eta_steps(vm["eta_steps"].as<std::size_t>());
0070 cfg.seed(vm["random_seed"].as<std::size_t>());
0071 cfg.randomize_charge(vm.count("randomize_charge"));
0072
0073 if (vm.count("eta_range") != 0u) {
0074 const auto eta_range = vm["eta_range"].as<std::vector<scalar_t>>();
0075 if (eta_range.size() == 2u) {
0076 cfg.eta_range(eta_range[0], eta_range[1]);
0077 } else {
0078 throw std::invalid_argument("Eta range needs two arguments");
0079 }
0080 }
0081 if (vm.count("origin") != 0u) {
0082 const auto origin = vm["origin"].as<std::vector<scalar_t>>();
0083 if (origin.size() == 3u) {
0084 cfg.origin(origin[0] * unit<scalar_t>::mm, origin[1] * unit<scalar_t>::mm,
0085 origin[2] * unit<scalar_t>::mm);
0086 } else {
0087 throw std::invalid_argument("Particle gun origin needs three arguments");
0088 }
0089 }
0090 if (vm.count("pT_range") != 0u && vm.count("p_range") != 0u) {
0091 throw std::invalid_argument(
0092 "Transverse and total momentum cannot be specified at the same "
0093 "time");
0094 }
0095 if (vm.count("pT_range") != 0u) {
0096 const auto pt_range = vm["pT_range"].as<std::vector<scalar_t>>();
0097
0098
0099 if (pt_range.empty()) {
0100 cfg.p_T(static_cast<scalar_t>(cfg.m_p_mag));
0101 } else if (pt_range.size() <= 2u) {
0102 if (pt_range.size() == 2u) {
0103 DETRAY_ERROR_HOST(
0104 "Momentum range not possible with uniform "
0105 "track generator: Using first value.");
0106 }
0107 cfg.p_T(pt_range[0] * unit<scalar_t>::GeV);
0108 } else {
0109 throw std::invalid_argument(
0110 "Wrong number of arguments for pT range: Need one argument or "
0111 "range");
0112 }
0113 } else {
0114 auto p_range = std::vector<scalar_t>{};
0115 if (vm.count("pT_range") != 0u) {
0116 p_range = vm["p_range"].as<std::vector<scalar_t>>();
0117 }
0118
0119
0120 if (p_range.empty()) {
0121 cfg.p_tot(static_cast<scalar_t>(cfg.m_p_mag));
0122 } else if (p_range.size() <= 2u) {
0123 if (p_range.size() == 2u) {
0124 DETRAY_ERROR_HOST(
0125 "Momentum range not possible with uniform "
0126 "track generator: Using first value.");
0127 }
0128 cfg.p_tot(p_range[0] * unit<scalar_t>::GeV);
0129 } else {
0130 std::string err_str{
0131 "Wrong number of arguments for p_tot range: Need one argument "
0132 "or range"};
0133 DETRAY_FATAL_HOST(err_str);
0134 throw std::invalid_argument(err_str);
0135 }
0136 }
0137 }
0138
0139
0140 template <concepts::scalar scalar_t>
0141 void add_rnd_track_gen_options(
0142 boost::program_options::options_description &desc,
0143 const random_track_generator_config<scalar_t> &cfg) {
0144 desc.add_options()(
0145 "n_tracks",
0146 boost::program_options::value<std::size_t>()->default_value(
0147 cfg.n_tracks()),
0148 "No. of tracks for particle gun")(
0149 "random_seed",
0150 boost::program_options::value<std::size_t>()->default_value(cfg.seed()),
0151 "Seed for the random number generator")(
0152 "theta_range",
0153 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0154 "Min, Max range of theta values for particle gun. Interval in [0, pi)")(
0155 "eta_range",
0156 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0157 "Min, Max range of eta values for particle gun")(
0158 "randomize_charge", "Randomly flip charge sign per track")(
0159 "origin",
0160 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0161 "Coordinates for particle gun origin position [mm]")(
0162 "p_range",
0163 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0164 "Total momentum [range] of the test particles [GeV]")(
0165 "pT_range",
0166 boost::program_options::value<std::vector<scalar_t>>()->multitoken(),
0167 "Transverse momentum [range] of the test particles [GeV]");
0168 }
0169
0170
0171 template <concepts::scalar scalar_t>
0172 void configure_rnd_track_gen_options(
0173 const boost::program_options::variables_map &vm,
0174 random_track_generator_config<scalar_t> &cfg) {
0175 cfg.n_tracks(vm["n_tracks"].as<std::size_t>());
0176 cfg.seed(vm["random_seed"].as<std::size_t>());
0177 cfg.randomize_charge(vm.count("randomize_charge"));
0178
0179 if (vm.count("eta_range") != 0u && vm.count("theta_range") != 0u) {
0180 throw std::invalid_argument(
0181 "Eta range and theta range cannot be specified at the same time");
0182 } else if (vm.count("eta_range") != 0u) {
0183 const auto eta_range = vm["eta_range"].as<std::vector<scalar_t>>();
0184 if (eta_range.size() == 2u) {
0185 scalar_t min_theta{2.f * std::atan(std::exp(-eta_range[0]))};
0186 scalar_t max_theta{2.f * std::atan(std::exp(-eta_range[1]))};
0187
0188
0189 if (min_theta > max_theta) {
0190 scalar_t tmp{min_theta};
0191 min_theta = max_theta;
0192 max_theta = tmp;
0193 }
0194
0195 cfg.theta_range(min_theta, max_theta);
0196 } else {
0197 throw std::invalid_argument("Eta range needs two arguments");
0198 }
0199 } else if (vm.count("theta_range") != 0u) {
0200 const auto theta_range = vm["theta_range"].as<std::vector<scalar_t>>();
0201 if (theta_range.size() == 2u) {
0202 cfg.theta_range(theta_range[0], theta_range[1]);
0203 } else {
0204 throw std::invalid_argument("Theta range needs two arguments");
0205 }
0206 }
0207 if (vm.count("origin") != 0u) {
0208 const auto origin = vm["origin"].as<std::vector<scalar_t>>();
0209 if (origin.size() == 3u) {
0210 cfg.origin(origin[0] * unit<scalar_t>::mm, origin[1] * unit<scalar_t>::mm,
0211 origin[2] * unit<scalar_t>::mm);
0212 } else {
0213 throw std::invalid_argument(
0214 "Particle gun origin needs three coordinates");
0215 }
0216 }
0217 if (vm.count("pT_range") != 0u && vm.count("p_range") != 0u) {
0218 throw std::invalid_argument(
0219 "Transverse and total momentum cannot be specified at the same "
0220 "time");
0221 }
0222 if (vm.count("pT_range") != 0u) {
0223 const auto pt_range = vm["pT_range"].as<std::vector<scalar_t>>();
0224
0225
0226 if (pt_range.empty()) {
0227 cfg.p_T(cfg.mom_range()[0]);
0228 } else if (pt_range.size() == 1u) {
0229 cfg.p_T(pt_range[0] * unit<scalar_t>::GeV);
0230 } else if (pt_range.size() == 2u) {
0231 cfg.pT_range(pt_range[0] * unit<scalar_t>::GeV,
0232 pt_range[1] * unit<scalar_t>::GeV);
0233 } else {
0234 throw std::invalid_argument(
0235 "Wrong number of arguments for pT range: Need one argument or "
0236 "range");
0237 }
0238 } else {
0239 auto p_range = std::vector<scalar_t>();
0240 if (vm.count("pT_range") != 0u) {
0241 p_range = vm["p_range"].as<std::vector<scalar_t>>();
0242 }
0243
0244
0245 if (p_range.empty()) {
0246 cfg.p_tot(cfg.mom_range()[0]);
0247 } else if (p_range.size() == 1u) {
0248 cfg.p_tot(p_range[0] * unit<scalar_t>::GeV);
0249 } else if (p_range.size() == 2u) {
0250 cfg.mom_range(p_range[0] * unit<scalar_t>::GeV,
0251 p_range[1] * unit<scalar_t>::GeV);
0252 } else {
0253 throw std::invalid_argument(
0254 "Wrong number of arguments for p_tot range: Need one argument "
0255 "or range");
0256 }
0257 }
0258 }
0259
0260 }
0261
0262
0263
0264 template <>
0265 void add_options<uniform_track_generator_config<float>>(
0266 boost::program_options::options_description &desc,
0267 const uniform_track_generator_config<float> &cfg) {
0268 detail::add_uniform_track_gen_options(desc, cfg);
0269 }
0270
0271 template <>
0272 void add_options<uniform_track_generator_config<double>>(
0273 boost::program_options::options_description &desc,
0274 const uniform_track_generator_config<double> &cfg) {
0275 detail::add_uniform_track_gen_options(desc, cfg);
0276 }
0277
0278
0279
0280
0281 template <>
0282 void configure_options<uniform_track_generator_config<float>>(
0283 const boost::program_options::variables_map &vm,
0284 uniform_track_generator_config<float> &cfg) {
0285 detail::configure_uniform_track_gen_options(vm, cfg);
0286 }
0287
0288 template <>
0289 void configure_options<uniform_track_generator_config<double>>(
0290 const boost::program_options::variables_map &vm,
0291 uniform_track_generator_config<double> &cfg) {
0292 detail::configure_uniform_track_gen_options(vm, cfg);
0293 }
0294
0295
0296
0297
0298 template <>
0299 void add_options<random_track_generator_config<float>>(
0300 boost::program_options::options_description &desc,
0301 const random_track_generator_config<float> &cfg) {
0302 detail::add_rnd_track_gen_options(desc, cfg);
0303 }
0304
0305 template <>
0306 void add_options<random_track_generator_config<double>>(
0307 boost::program_options::options_description &desc,
0308 const random_track_generator_config<double> &cfg) {
0309 detail::add_rnd_track_gen_options(desc, cfg);
0310 }
0311
0312
0313
0314
0315 template <>
0316 void configure_options<random_track_generator_config<float>>(
0317 const boost::program_options::variables_map &vm,
0318 random_track_generator_config<float> &cfg) {
0319 detail::configure_rnd_track_gen_options(vm, cfg);
0320 }
0321
0322 template <>
0323 void configure_options<random_track_generator_config<double>>(
0324 const boost::program_options::variables_map &vm,
0325 random_track_generator_config<double> &cfg) {
0326 detail::configure_rnd_track_gen_options(vm, cfg);
0327 }
0328
0329
0330 }