File indexing completed on 2025-01-18 09:11:56
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Root/RootBFieldWriter.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0014 #include "Acts/Utilities/VectorHelpers.hpp"
0015
0016 #include <cassert>
0017 #include <ios>
0018 #include <sstream>
0019 #include <stdexcept>
0020 #include <utility>
0021 #include <vector>
0022
0023 #include <TFile.h>
0024 #include <TTree.h>
0025
0026 namespace ActsExamples {
0027
0028
0029 void RootBFieldWriter::run(const Config& config,
0030 std::unique_ptr<const Acts::Logger> p_logger) {
0031
0032 ACTS_LOCAL_LOGGER(std::move(p_logger))
0033
0034 Acts::MagneticFieldContext bFieldContext;
0035
0036
0037 if (config.treeName.empty()) {
0038 throw std::invalid_argument("Missing tree name");
0039 } else if (config.fileName.empty()) {
0040 throw std::invalid_argument("Missing file name");
0041 } else if (config.bField == nullptr) {
0042 throw std::invalid_argument("Missing interpolated magnetic field");
0043 }
0044
0045
0046 ACTS_INFO("Registering new ROOT output File : " << config.fileName);
0047 std::unique_ptr<TFile> outputFile(
0048 TFile::Open(config.fileName.c_str(), config.fileMode.c_str()));
0049 if (outputFile == nullptr) {
0050 throw std::ios_base::failure("Could not open '" + config.fileName + "'");
0051 }
0052 TTree* outputTree = new TTree(config.treeName.c_str(),
0053 config.treeName.c_str(), 99, outputFile.get());
0054 if (outputTree == nullptr) {
0055 throw std::bad_alloc();
0056 }
0057
0058
0059 auto minima = config.bField->getMin();
0060 auto maxima = config.bField->getMax();
0061 auto nBins = config.bField->getNBins();
0062
0063 if (logger().doPrint(Acts::Logging::VERBOSE)) {
0064 std::stringstream ss;
0065 ss << "Minimum:";
0066 for (auto m : minima) {
0067 ss << " " << m;
0068 }
0069 ACTS_VERBOSE(ss.str());
0070 ss.str("");
0071 ss << "Maximum:";
0072 for (auto m : maxima) {
0073 ss << " " << m;
0074 }
0075 ACTS_VERBOSE(ss.str());
0076 ss.str("");
0077 ss << "nBins:";
0078 for (auto m : nBins) {
0079 ss << " " << m;
0080 }
0081 ACTS_VERBOSE(ss.str());
0082 }
0083
0084 if (config.gridType == GridType::xyz) {
0085 ACTS_INFO("Map will be written out in cartesian coordinates (x,y,z).");
0086
0087
0088 double minX = 0., minY = 0., minZ = 0.;
0089 double maxX = 0., maxY = 0., maxZ = 0.;
0090 std::size_t nBinsX = 0, nBinsY = 0, nBinsZ = 0;
0091
0092
0093 double x = 0;
0094 outputTree->Branch("x", &x);
0095 double y = 0;
0096 outputTree->Branch("y", &y);
0097 double z = 0;
0098 outputTree->Branch("z", &z);
0099
0100
0101 double Bx = 0;
0102 outputTree->Branch("Bx", &Bx);
0103 double By = 0;
0104 outputTree->Branch("By", &By);
0105 double Bz = 0;
0106 outputTree->Branch("Bz", &Bz);
0107
0108
0109 if (config.rBounds && config.zBounds) {
0110 ACTS_INFO("User defined ranges handed over.");
0111
0112
0113 minX = config.rBounds->at(0);
0114 minY = config.rBounds->at(0);
0115 minZ = config.zBounds->at(0);
0116
0117 maxX = config.rBounds->at(1);
0118 maxY = config.rBounds->at(1);
0119 maxZ = config.zBounds->at(1);
0120
0121 nBinsX = config.rBins;
0122 nBinsY = config.rBins;
0123 nBinsZ = config.zBins;
0124
0125 } else {
0126 ACTS_INFO("No user defined ranges handed over - write out whole map.");
0127
0128
0129
0130 if (minima.size() == 3 && maxima.size() == 3) {
0131 minX = minima.at(0);
0132 minY = minima.at(1);
0133 minZ = minima.at(2);
0134
0135 maxX = maxima.at(0);
0136 maxY = maxima.at(1);
0137 maxZ = maxima.at(2);
0138
0139 nBinsX = nBins.at(0);
0140 nBinsY = nBins.at(1);
0141 nBinsZ = nBins.at(2);
0142
0143 } else if (minima.size() == 2 && maxima.size() == 2) {
0144 minX = -maxima.at(0);
0145 minY = -maxima.at(0);
0146 minZ = minima.at(1);
0147
0148 maxX = maxima.at(0);
0149 maxY = maxima.at(0);
0150 maxZ = maxima.at(1);
0151
0152 nBinsX = nBins.at(0);
0153 nBinsY = nBins.at(0);
0154 nBinsZ = nBins.at(1);
0155 } else {
0156 throw std::invalid_argument(
0157 "BField has wrong dimension. The dimension needs to be "
0158 "either 2 (r,z,Br,Bz) or 3(x,y,z,Bx,By,Bz) in order to be "
0159 "written out by this writer.");
0160 }
0161 }
0162
0163 assert(maxX > minX);
0164 assert(maxY > minY);
0165 assert(maxZ > minZ);
0166
0167 double stepX = (maxX - minX) / (nBinsX - 1);
0168 double stepY = (maxY - minY) / (nBinsY - 1);
0169 double stepZ = (maxZ - minZ) / (nBinsZ - 1);
0170
0171 for (std::size_t i = 0; i < nBinsX; i++) {
0172 double raw_x = minX + i * stepX;
0173 for (std::size_t j = 0; j < nBinsY; j++) {
0174 double raw_y = minY + j * stepY;
0175 for (std::size_t k = 0; k < nBinsZ; k++) {
0176 double raw_z = minZ + k * stepZ;
0177 Acts::Vector3 position(raw_x, raw_y, raw_z);
0178 Acts::Vector3 bField = config.bField->getFieldUnchecked(position);
0179
0180 x = raw_x / Acts::UnitConstants::mm;
0181 y = raw_y / Acts::UnitConstants::mm;
0182 z = raw_z / Acts::UnitConstants::mm;
0183 Bx = bField.x() / Acts::UnitConstants::T;
0184 By = bField.y() / Acts::UnitConstants::T;
0185 Bz = bField.z() / Acts::UnitConstants::T;
0186 outputTree->Fill();
0187 }
0188 }
0189 }
0190
0191 } else {
0192 ACTS_INFO("Map will be written out in cylinder coordinates (r,z).");
0193
0194
0195 double r = 0;
0196 outputTree->Branch("r", &r);
0197 double z = 0;
0198 outputTree->Branch("z", &z);
0199
0200 double Br = 0;
0201 outputTree->Branch("Br", &Br);
0202 double Bz = 0;
0203 outputTree->Branch("Bz", &Bz);
0204
0205 double minR = 0, maxR = 0;
0206 double minZ = 0, maxZ = 0;
0207 std::size_t nBinsR = 0, nBinsZ = 0;
0208
0209 if (config.rBounds && config.zBounds) {
0210 ACTS_INFO("User defined ranges handed over.");
0211
0212 minR = config.rBounds->at(0);
0213 minZ = config.zBounds->at(0);
0214
0215 maxR = config.rBounds->at(1);
0216 maxZ = config.zBounds->at(1);
0217
0218 nBinsR = config.rBins;
0219 nBinsZ = config.zBins;
0220 } else {
0221 ACTS_INFO("No user defined ranges handed over - printing out whole map.");
0222
0223 if (minima.size() == 3 && maxima.size() == 3) {
0224 minR = 0.;
0225 minZ = minima.at(2);
0226
0227 maxR = maxima.at(0);
0228 maxZ = maxima.at(2);
0229
0230 nBinsR = nBins.at(0);
0231 nBinsZ = nBins.at(2);
0232
0233 } else if (minima.size() == 2 || maxima.size() == 2) {
0234 minR = minima.at(0);
0235 minZ = minima.at(1);
0236
0237 maxR = maxima.at(0);
0238 maxZ = maxima.at(1);
0239
0240 nBinsR = nBins.at(0);
0241 nBinsZ = nBins.at(1);
0242
0243 } else {
0244 throw std::invalid_argument(
0245 "BField has wrong dimension. The dimension needs to be "
0246 "either 2 (r,z,Br,Bz) or 3(x,y,z,Bx,By,Bz) in order to be "
0247 "written out by this writer.");
0248 }
0249 }
0250
0251 assert(maxR > minR);
0252 assert(maxZ > minZ);
0253
0254 double stepR = (maxR - minR) / (nBinsR - 1);
0255 double stepZ = (maxZ - minZ) / (nBinsZ - 1);
0256
0257 for (std::size_t k = 0; k < nBinsZ; k++) {
0258 double raw_z = minZ + k * stepZ;
0259 for (std::size_t j = 0; j < nBinsR; j++) {
0260 double raw_r = minR + j * stepR;
0261 Acts::Vector3 position(raw_r, 0.0, raw_z);
0262 ACTS_VERBOSE("Requesting position: " << position.transpose());
0263 auto bField = config.bField->getFieldUnchecked(position);
0264 z = raw_z / Acts::UnitConstants::mm;
0265 r = raw_r / Acts::UnitConstants::mm;
0266 Bz = bField.z() / Acts::UnitConstants::T;
0267 Br = Acts::VectorHelpers::perp(bField) / Acts::UnitConstants::T;
0268 outputTree->Fill();
0269 }
0270 }
0271 }
0272
0273
0274 ACTS_INFO("Closing and Writing ROOT output File : " << config.fileName);
0275 outputTree->Write();
0276 }
0277
0278 }