27 #include <boost/program_options.hpp>
30 using boost::program_options::bool_switch;
34 if (desc.find_nothrow(
"bf-constant-tesla",
true) !=
nullptr) {
38 auto opt = desc.add_options();
40 "Set a constant magnetic field vector in Tesla. If given, this takes "
41 "preference over all other options.");
42 opt(
"bf-scalable", bool_switch(),
43 "If given, the constant field strength will be scaled differently in "
44 "every event. This is for testing only.");
45 opt(
"bf-scalable-scalor", value<double>()->default_value(1.25),
46 "Scaling factor for the event-dependent field strength scaling. A unit "
47 "value means that the field strength stays the same for every event.");
48 opt(
"bf-map-file", value<std::string>(),
49 "Read a magnetic field map from the given file. ROOT and text file "
50 "formats are supported. Only used if no constant field is given.");
51 opt(
"bf-map-tree", value<std::string>()->default_value(
"bField"),
52 "Name of the TTree in the ROOT file. Only used if the field map is read "
54 opt(
"bf-map-type", value<std::string>()->default_value(
"xyz"),
55 "Either 'xyz' or 'rz' to define the type of the field map.");
56 opt(
"bf-map-octantonly", bool_switch(),
57 "If given, the field map is assumed to describe only the first "
58 "octant/quadrant and the field is symmetrically extended to the full "
60 opt(
"bf-map-lengthscale-mm", value<double>()->default_value(1.),
61 "Optional length scale modifier for the field map grid. This options "
62 "only needs to be set if the length unit in the field map file is not "
63 "`mm`. The value must scale from the stored unit to the equivalent value "
65 opt(
"bf-map-fieldscale-tesla", value<double>()->default_value(1.),
66 "Optional field value scale modifier for the field map value. This "
67 "option only needs to be set if the field value unit in the field map "
68 "file is not `Tesla`. The value must scale from the stored unit to the "
69 "equivalent value in `Tesla`.");
70 opt(
"bf-solenoid-mag-tesla", value<double>()->default_value(0.),
71 "The magnitude of a solenoid magnetic field in the center in `Tesla`. "
73 "if neither constant field nor a magnetic field map is given.");
74 opt(
"bf-solenoid-length", value<double>()->default_value(6000),
75 "The length of the solenoid magnetic field in `mm`.");
76 opt(
"bf-solenoid-radius", value<double>()->default_value(1200),
77 "The radius of the solenoid magnetic field in `mm`.");
78 opt(
"bf-solenoid-ncoils", value<size_t>()->default_value(1194),
79 "Number of coils for the solenoid magnetic field.");
80 opt(
"bf-solenoid-map-rlim",
81 value<Interval>()->value_name(
"MIN:MAX")->default_value({0, 1200}),
82 "The length bounds of the grid created from the analytical solenoid "
84 opt(
"bf-solenoid-map-zlim",
85 value<Interval>()->value_name(
"MIN:MAX")->default_value({-3000, 3000}),
86 "The radius bounds of the grid created from the analytical solenoid "
88 opt(
"bf-solenoid-map-nbins",
value<
Reals<2>>()->default_value({{150, 200}}),
89 "The number of bins in r-z directions for the grid created from the "
90 "analytical solenoid field.");
95 if (vars[
"bf-scalable"].as<bool>()) {
97 sbfCfg.
scalor = vars[
"bf-scalable-scalor"].as<
double>();
103 std::shared_ptr<Acts::MagneticFieldProvider>
105 using namespace ActsExamples::detail;
112 if (vars.count(
"bf-constant-tesla") != 0
u) {
115 values[1] * Acts::UnitConstants::T,
116 values[2] * Acts::UnitConstants::T);
117 if (vars[
"bf-scalable"].as<bool>()) {
118 ACTS_INFO(
"Use a constant magnetic field with per-event scaling");
119 return std::make_shared<ScalableBField>(
field);
121 ACTS_INFO(
"Use a constant magnetic field");
122 return std::make_shared<Acts::ConstantBField>(
field);
127 if (vars.count(
"bf-map-file") != 0
u) {
131 const auto useOctantOnly = vars[
"bf-map-octantonly"].as<
bool>();
134 const auto fieldUnit =
137 bool readRoot =
false;
138 if (file.extension() ==
".root") {
139 ACTS_INFO(
"Read magnetic field map from ROOT file '" << file <<
"'");
141 }
else if (file.extension() ==
".txt") {
142 ACTS_INFO(
"Read magnetic field map from text file '" << file <<
"'");
146 <<
"' is an unsupported magnetic field map file type");
147 throw std::runtime_error(
"Unsupported magnetic field map file type");
151 auto mapBins = [](std::array<size_t, 3>
bins,
152 std::array<size_t, 3> sizes) {
153 return (bins[0] * (sizes[1] * sizes[2]) + bins[1] * sizes[2] + bins[2]);
161 return std::make_shared<InterpolatedMagneticField3>(
std::move(map));
166 fieldUnit, useOctantOnly);
167 return std::make_shared<InterpolatedMagneticField3>(
std::move(map));
170 }
else if (type ==
"rz") {
171 auto mapBins = [](std::array<size_t, 2>
bins,
172 std::array<size_t, 2> sizes) {
173 return (bins[1] * sizes[0] + bins[0]);
181 return std::make_shared<InterpolatedMagneticField2>(
std::move(map));
186 fieldUnit, useOctantOnly);
187 return std::make_shared<InterpolatedMagneticField2>(
std::move(map));
191 ACTS_ERROR(
"'" << type <<
"' is an unknown magnetic field map type");
192 throw std::runtime_error(
"Unknown magnetic field map type");
197 if (vars[
"bf-solenoid-mag-tesla"].as<double>() > 0) {
202 solenoidConfig.radius =
204 solenoidConfig.nCoils = vars[
"bf-solenoid-ncoils"].as<
size_t>();
205 solenoidConfig.bMagCenter =
207 ACTS_INFO(
"Use solenoid magnetic field with magnitude "
209 <<
" Tesla at the center.");
212 auto getRange = [&](
const char*
name,
auto unit,
auto&
lower,
auto&
upper) {
214 lower =
interval.lower.value() * unit;
217 std::pair<double, double> rlim, zlim;
222 const auto nbins = vars[
"bf-solenoid-map-nbins"].as<
Reals<2>>();
225 return std::make_shared<InterpolatedMagneticField2>(
std::move(map));
230 return std::make_shared<Acts::NullBField>();