EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BFieldOptions.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file BFieldOptions.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 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 
14 #include "Acts/Utilities/Units.hpp"
18 
19 #include <iostream>
20 #include <tuple>
21 #include <utility>
22 
23 #include <boost/program_options.hpp>
24 
25 namespace po = boost::program_options;
26 
30 
34 
39 
40 namespace ActsExamples {
41 
42 namespace Options {
43 
44 // common bfield options, with a bf prefix
45 void addBFieldOptions(boost::program_options::options_description& opt) {
46  opt.add_options()("bf-map", po::value<std::string>()->default_value(""),
47  "Set this string to point to the bfield source file."
48  "That can either be a '.txt', a '.csv' or a '.root' file. "
49  "Omit for a constant magnetic field.")(
50  "bf-name", po::value<std::string>()->default_value("bField"),
51  "In case your field map file is given in root format, please specify "
52  "the "
53  "name of the TTree.")(
54  "bf-gridpoints", po::value<size_t>()->default_value(100000),
55  "Estimate of number of grid points, "
56  "needed for allocation, only for txt and csv files.")(
57  "bf-lscalor", po::value<double>()->default_value(1.),
58  "The default unit for the grid "
59  "points is mm. In case the grid points of your field map has another "
60  "unit, please set the scalor to mm.")(
61  "bf-bscalor", po::value<double>()->default_value(1.),
62  "The default unit for the magnetic field values is Tesla. In case the "
63  "grid points of your field map has another unit, please set the "
64  "scalor "
65  "to [T].")(
66  "bf-rz", po::value<bool>()->default_value(false),
67  "Please set this flag to true, if your grid points and your "
68  "magnetic field values are given in 'rz'. The default is 'xyz'.")(
69  "bf-foctant", po::value<bool>()->default_value(false),
70  "Please set this flag to true, if your field map is only given for the "
71  "first octant/quadrant and should be symmetrically created for all "
72  "other "
73  "octants/quadrants.")(
74  "bf-values",
75  po::value<read_range>()->multitoken()->default_value({0., 0., 0.}),
76  "In case no magnetic field map is handed over. A constant magnetic "
77  "field will be created automatically. The values can be set with this "
78  "options. Please hand over the coordinates in cartesian coordinates: "
79  "{Bx,By,Bz} in Tesla.")(
80  "bf-context-scalable", po::value<bool>()->default_value(false),
81  "This is for testing the event dependent magnetic field scaling.");
82 }
83 
84 // create the bfield maps
85 BFieldVariant readBField(const boost::program_options::variables_map& vm) {
86  std::string bfieldmap = "constfield";
87 
88  enum BFieldMapType { constant = 0, root = 1, text = 2 };
89 
90  std::shared_ptr<InterpolatedBFieldMap2D> map2D = nullptr;
91  std::shared_ptr<InterpolatedBFieldMap3D> map3D = nullptr;
92  std::shared_ptr<Acts::ConstantBField> mapConst = nullptr;
93  std::shared_ptr<ActsExamples::BField::ScalableBField> mapScale = nullptr;
94 
95  int bfieldmaptype = constant;
96  if (vm.count("bf-map") && vm["bf-map"].template as<std::string>() != "") {
97  bfieldmap = vm["bf-map"].template as<std::string>();
98  std::cout << "- read in magnetic field map: "
99  << vm["bf-map"].template as<std::string>() << std::endl;
100  if (bfieldmap.find(".root") != std::string::npos) {
101  std::cout << "- root format for magnetic field detected" << std::endl;
102  bfieldmaptype = root;
103  } else if (bfieldmap.find(".txt") != std::string::npos ||
104  bfieldmap.find(".csv") != std::string::npos) {
105  std::cout << "- txt format for magnetic field detected" << std::endl;
106  bfieldmaptype = text;
107  } else {
108  std::cout << "- magnetic field format could not be detected";
109  std::cout << " use '.root', '.txt', or '.csv'." << std::endl;
110  throw std::runtime_error("Invalid BField options");
111  }
112  }
113  if (bfieldmaptype == text && vm.count("bf-gridpoints")) {
114  std::cout << "- number of points set to: "
115  << vm["bf-gridpoints"].template as<size_t>() << std::endl;
116  }
117  double lscalor = 1.;
118  if (bfieldmaptype != constant && vm.count("bf-lscalor")) {
119  lscalor = vm["bf-lscalor"].template as<double>();
120  std::cout << "- length scalor to mm set to: " << lscalor << std::endl;
121  }
122  double bscalor = 1.;
123  if (vm.count("bf-bscalor")) {
124  bscalor = vm["bf-bscalor"].template as<double>();
125  std::cout << "- BField (scalor to/in) Tesla set to: " << bscalor
126  << std::endl;
127  }
128  if (bfieldmaptype != constant && vm["bf-rz"].template as<bool>())
129  std::cout << "- BField map is given in 'rz' coordiantes." << std::endl;
130  else if (bfieldmaptype != constant)
131  std::cout << "- BField map is given in 'xyz' coordiantes." << std::endl;
132 
133  if (bfieldmaptype != constant && vm["bf-foctant"].template as<bool>()) {
134  std::cout
135  << "- Only the first octant/quadrant is given, bField map will be "
136  "symmetrically created for all other octants/quadrants"
137  << std::endl;
138  }
139 
140  // Declare the mapper
141  double lengthUnit = lscalor * Acts::UnitConstants::mm;
142  double BFieldUnit = bscalor * Acts::UnitConstants::T;
143 
144  // set the mapper - foort
145  if (bfieldmaptype == root) {
146  if (vm["bf-rz"].template as<bool>()) {
148  [](std::array<size_t, 2> binsRZ, std::array<size_t, 2> nBinsRZ) {
149  return (binsRZ.at(1) * nBinsRZ.at(0) + binsRZ.at(0));
150  },
151  vm["bf-map"].template as<std::string>(),
152  vm["bf-name"].template as<std::string>(), lengthUnit, BFieldUnit,
153  vm["bf-foctant"].template as<bool>());
154 
155  // create field mapping
156  InterpolatedBFieldMap2D::Config config2D(std::move(mapper2D));
157  config2D.scale = bscalor;
158  // create BField service
159  return std::make_shared<InterpolatedBFieldMap2D>(std::move(config2D));
160 
161  } else {
163  [](std::array<size_t, 3> binsXYZ, std::array<size_t, 3> nBinsXYZ) {
164  return (binsXYZ.at(0) * (nBinsXYZ.at(1) * nBinsXYZ.at(2)) +
165  binsXYZ.at(1) * nBinsXYZ.at(2) + binsXYZ.at(2));
166  },
167  vm["bf-map"].template as<std::string>(),
168  vm["bf-name"].template as<std::string>(), lengthUnit, BFieldUnit,
169  vm["bf-foctant"].template as<bool>());
170 
171  // create field mapping
172  InterpolatedBFieldMap3D::Config config3D(std::move(mapper3D));
173  config3D.scale = bscalor;
174  // create BField service
175  return std::make_shared<InterpolatedBFieldMap3D>(std::move(config3D));
176  }
177  } else if (bfieldmaptype == text) {
178  if (vm["bf-rz"].template as<bool>()) {
180  [](std::array<size_t, 2> binsRZ, std::array<size_t, 2> nBinsRZ) {
181  return (binsRZ.at(1) * nBinsRZ.at(0) + binsRZ.at(0));
182  },
183  vm["bf-map"].template as<std::string>(), lengthUnit, BFieldUnit,
184  vm["bf-gridpoints"].template as<size_t>(),
185  vm["bf-foctant"].template as<bool>());
186 
187  // create field mapping
188  InterpolatedBFieldMap2D::Config config2D(std::move(mapper2D));
189  config2D.scale = bscalor;
190  // create BField service
191  return std::make_shared<InterpolatedBFieldMap2D>(std::move(config2D));
192 
193  } else {
195  [](std::array<size_t, 3> binsXYZ, std::array<size_t, 3> nBinsXYZ) {
196  return (binsXYZ.at(0) * (nBinsXYZ.at(1) * nBinsXYZ.at(2)) +
197  binsXYZ.at(1) * nBinsXYZ.at(2) + binsXYZ.at(2));
198  },
199  vm["bf-map"].template as<std::string>(), lengthUnit, BFieldUnit,
200  vm["bf-gridpoints"].template as<size_t>(),
201  vm["bf-foctant"].template as<bool>());
202 
203  // create field mapping
204  InterpolatedBFieldMap3D::Config config3D(std::move(mapper3D));
205  config3D.scale = bscalor;
206  // create BField service
207  return std::make_shared<InterpolatedBFieldMap3D>(std::move(config3D));
208  }
209  } else { // constant
210  // No bfield map is handed over
211  // get the constant bField values
212  auto bFieldValues = vm["bf-values"].template as<read_range>();
213  if (bFieldValues.size() != 3) {
214  throw std::invalid_argument(
215  "- The values handed over for the constant magnetic field "
216  "have wrong dimension. Needs to have 3 dimension. Please "
217  "hand over the coordinates in cartesian coordinates: "
218  "{Bx,By,Bz} in Tesla.");
219  }
220  if (vm["bf-context-scalable"].template as<bool>()) {
221  // Create the scalable magnetic field
222  return std::make_shared<ActsExamples::BField::ScalableBField>(
223  bFieldValues.at(0) * Acts::UnitConstants::T,
224  bFieldValues.at(1) * Acts::UnitConstants::T,
225  bFieldValues.at(2) * Acts::UnitConstants::T);
226  } else {
227  // Create the constant magnetic field
228  return std::make_shared<Acts::ConstantBField>(
229  bscalor * bFieldValues.at(0) * Acts::UnitConstants::T,
230  bscalor * bFieldValues.at(1) * Acts::UnitConstants::T,
231  bscalor * bFieldValues.at(2) * Acts::UnitConstants::T);
232  }
233  }
234 }
235 } // namespace Options
236 } // namespace ActsExamples