9 #include <geometry/modules/CreateFieldMapModule.h>
10 #include <framework/geometry/BFieldManager.h>
11 #include <framework/utilities/Utils.h>
12 #include <framework/gearbox/Unit.h>
13 #include <framework/geometry/B2Vector3.h>
19 #include <boost/algorithm/string.hpp>
20 #include <boost/format.hpp>
35 setDescription(
"Create Field maps of the Belle II magnetic field used in the simulation");
38 addParam(
"filename", m_filename,
"ROOT filename for the map", std::string(
"FieldMap.root"));
39 addParam(
"type", m_type,
"type of the fieldmap (xy, zx, zy, zr)", std::string(
"zx"));
40 addParam(
"nU", m_nU,
"number of steps along first coordinate", 1800);
41 addParam(
"minU", m_minU,
"minimum value for the first coordinate", -400.);
42 addParam(
"maxU", m_maxU,
"maximum value for the first coordinate", 500.);
43 addParam(
"nV", m_nV,
"number of steps along second coordinate", 1600);
44 addParam(
"minV", m_minV,
"minimum value for the second coordinate", -400.);
45 addParam(
"maxV", m_maxV,
"maximum value for the second coordinate", 400.);
46 addParam(
"phi", m_phi,
"phi angle for the scan in radians", 0.);
47 addParam(
"wOffset", m_wOffset,
"value of third coordinate", 0.);
48 addParam(
"nPhi", m_nPhi,
"number of phi steps for zr averaging", m_nPhi);
49 addParam(
"saveAllPoints", m_createTree,
"save all sampled points in a TTree, "
50 "WARNING: output can be huge",
false);
56 B2WARNING(
"CreateFieldMap: No Filename given, just sampling for fun");
61 B2ERROR(
"CreateFieldMap type '" <<
m_type <<
"' not valid, use one of 'xy', 'zx', 'zy' or 'zr'");
64 B2ERROR(
"Number of steps has to be positive");
67 B2ERROR(
"Range for first coordinate is zero");
72 B2ERROR(
"Range for second coordinate is zero");
78 B2ERROR(
"R values (minV, maxV) must be positive");
81 B2ERROR(
"Number of steps in phi must be positive");
89 TFile* outfile{
nullptr};
92 outfile =
new TFile(
m_filename.c_str(),
"RECREATE");
110 auto showProgress = [&]() {
112 const int64_t donePercent = 100 * ++curStep / nSteps;
113 if (donePercent > lastPercent) {
115 const double perStep = totalTime / curStep;
116 if (donePercent == 100) {
117 B2INFO(boost::format(
"BField %s Scan: %d samples, %.3f us per sample, total: %.2f seconds")
121 B2INFO(boost::format(
"BField %s Scan: %3d%%, %.3f us per sample")
125 lastPercent = donePercent;
129 struct {
float x{0}, y{0}, z{0}, bx{0}, by{0}, bz{0}; } field_point;
130 TTree* all_values{
nullptr};
132 all_values =
new TTree(
"bfield_values",
"All B field values");
133 all_values->Branch(
"x", &field_point.x,
"x/F");
134 all_values->Branch(
"y", &field_point.y,
"y/F");
135 all_values->Branch(
"z", &field_point.z,
"z/F");
136 all_values->Branch(
"bx", &field_point.bx,
"bx/F");
137 all_values->Branch(
"by", &field_point.by,
"by/F");
138 all_values->Branch(
"bz", &field_point.bz,
"bz/F");
141 if (!all_values)
return;
142 field_point.x = p.X();
143 field_point.y = p.Y();
144 field_point.z = p.Z();
145 field_point.bx = b.X();
146 field_point.by = b.Y();
147 field_point.bz = b.Z();
156 for (
int iU = 0; iU <
m_nU; ++iU) {
157 for (
int iV = 0; iV <
m_nV; ++iV) {
159 const double u = h_b->GetXaxis()->GetBinCenter(iU + 1);
160 const double v = h_b->GetYaxis()->GetBinCenter(iV + 1);
162 for (
int iPhi = 0; iPhi <
m_nPhi; ++iPhi) {
164 pos.RotateZ(2 * M_PI * iPhi /
m_nPhi);
169 h_br->Fill(u, v, bfield.
Perp());
170 h_bz->Fill(u, v, bfield.
Z());
171 h_b->Fill(u, v, bfield.
Mag());
172 fillTree(pos, bfield);
180 for (TH2D* h : {h_br, h_bz, h_b}) {
186 const std::string nu =
m_type.substr(0, 1);
187 const std::string nv =
m_type.substr(1, 1);
194 for (
int iU = 0; iU <
m_nU; ++iU) {
195 for (
int iV = 0; iV <
m_nV; ++iV) {
198 const double u = h_bx->GetXaxis()->GetBinCenter(iU + 1);
199 const double v = h_bx->GetYaxis()->GetBinCenter(iV + 1);
219 h_bx->Fill(u, v, bfield.
X());
220 h_by->Fill(u, v, bfield.
Y());
221 h_bz->Fill(u, v, bfield.
Z());
222 h_b->Fill(u, v, bfield.
Mag());
223 fillTree(pos, bfield);
230 for (TH2D* h : {h_bx, h_by, h_bz, h_b}) {
236 if (all_values) all_values->Write();
DataType Z() const
access variable Z (= .at(2) without boundary check)
DataType X() const
access variable X (= .at(0) without boundary check)
DataType Y() const
access variable Y (= .at(1) without boundary check)
DataType Mag() const
The magnitude (rho in spherical coordinate system).
DataType Perp() const
The transverse component (R in cylindrical coordinate system).
static B2Vector3D getFieldInTesla(const B2Vector3D &pos)
return the magnetic field at a given position in Tesla.
Create Field maps of the Belle II magnetic field used in the simulation.
int m_nPhi
number of steps in phi
virtual void initialize() override
Check input parameters.
double m_minV
start value for the first coordinate
double m_wOffset
offset on the third coordinate
double m_minU
start value for the first coordinate
double m_phi
phi rotation when sampling magnetic field (value of pi will convert ZX to ZY scan)
int m_nV
number of steps along the second coordinate
int m_nU
number of steps along the first coordinate
std::string m_type
type of the fieldmap (zx, zy, zr)
double m_maxV
end value for the first coordinate
virtual void beginRun() override
Create the fieldmap.
std::string m_filename
output filename for the fieldmap
EFieldTypes
Types of Fieldmap to be created.
@ c_ZX
scan along ZX plane
@ c_ZY
scan along ZY plane
@ c_ZR
scan along Z and R, averaging over phi
@ c_XY
scan along XY plane
double m_maxU
end value for the first coordinate
bool m_createTree
if true create a TTree with all sampled points
static const double us
[microsecond]
static const double s
[second]
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
double getClock()
Return current value of the real-time clock.
Abstract base class for different kinds of events.