EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MaterialMapUtils.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MaterialMapUtils.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019-2020 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 
15 #include <iostream>
16 #include <limits>
17 
20 
22  const std::function<size_t(std::array<size_t, 2> binsRZ,
23  std::array<size_t, 2> nBinsRZ)>&
24  materialVectorToGridMapper,
25  std::vector<double> rPos, std::vector<double> zPos,
26  std::vector<Acts::Material> material, double lengthUnit)
28  detail::EquidistantAxis>> {
29  // [1] Decompose material
30  std::vector<ActsVectorF<5>> materialVector;
31  materialVector.reserve(material.size());
32 
33  for (Material& mat : material) {
34  materialVector.push_back(mat.parameters());
35  }
36 
37  // [2] Create Grid
38  // sort the values
39  std::sort(rPos.begin(), rPos.end());
40  std::sort(zPos.begin(), zPos.end());
41  // Get unique values
42  rPos.erase(std::unique(rPos.begin(), rPos.end()), rPos.end());
43  zPos.erase(std::unique(zPos.begin(), zPos.end()), zPos.end());
44  rPos.shrink_to_fit();
45  zPos.shrink_to_fit();
46  // get the number of bins
47  size_t nBinsR = rPos.size();
48  size_t nBinsZ = zPos.size();
49 
50  // get the minimum and maximum
51  auto minMaxR = std::minmax_element(rPos.begin(), rPos.end());
52  auto minMaxZ = std::minmax_element(zPos.begin(), zPos.end());
53  double rMin = *minMaxR.first;
54  double zMin = *minMaxZ.first;
55  double rMax = *minMaxR.second;
56  double zMax = *minMaxZ.second;
57  // calculate maxima (add one last bin, because bin value always corresponds to
58  // left boundary)
59  double stepZ = std::fabs(zMax - zMin) / (nBinsZ - 1);
60  double stepR = std::fabs(rMax - rMin) / (nBinsR - 1);
61  rMax += stepR;
62  zMax += stepZ;
63 
64  // Create the axis for the grid
65  detail::EquidistantAxis rAxis(rMin * lengthUnit, rMax * lengthUnit, nBinsR);
66  detail::EquidistantAxis zAxis(zMin * lengthUnit, zMax * lengthUnit, nBinsZ);
67 
68  // Create the grid
70  detail::EquidistantAxis>;
71  Grid_t grid(std::make_tuple(std::move(rAxis), std::move(zAxis)));
72 
73  // [3] Set the material values
74  for (size_t i = 1; i <= nBinsR; ++i) {
75  for (size_t j = 1; j <= nBinsZ; ++j) {
76  std::array<size_t, 2> nIndices = {{rPos.size(), zPos.size()}};
77  Grid_t::index_t indices = {{i, j}};
78  // std::vectors begin with 0 and we do not want the user needing to
79  // take underflow or overflow bins in account this is why we need to
80  // subtract by one
81  grid.atLocalBins(indices) = materialVector.at(
82  materialVectorToGridMapper({{i - 1, j - 1}}, nIndices));
83  }
84  }
85  ActsVectorF<5> vec;
87  0., 0., 0.;
88  grid.setExteriorBins(vec);
89 
90  // [4] Create the transformation for the position
91  // map (x,y,z) -> (r,z)
92  auto transformPos = [](const Vector3D& pos) {
93  return Vector2D(perp(pos), pos.z());
94  };
95 
96  // [5] Create the mapper & BField Service
97  // create material mapping
99  detail::EquidistantAxis>>(transformPos,
100  std::move(grid));
101 }
102 
104  const std::function<size_t(std::array<size_t, 3> binsXYZ,
105  std::array<size_t, 3> nBinsXYZ)>&
106  materialVectorToGridMapper,
107  std::vector<double> xPos, std::vector<double> yPos,
108  std::vector<double> zPos, std::vector<Material> material, double lengthUnit)
109  -> MaterialMapper<
111  detail::EquidistantAxis, detail::EquidistantAxis>> {
112  // [1] Decompose material
113  std::vector<ActsVectorF<5>> materialVector;
114  materialVector.reserve(material.size());
115 
116  for (Material& mat : material) {
117  materialVector.push_back(mat.parameters());
118  }
119 
120  // [2] Create Grid
121  // Sort the values
122  std::sort(xPos.begin(), xPos.end());
123  std::sort(yPos.begin(), yPos.end());
124  std::sort(zPos.begin(), zPos.end());
125  // Get unique values
126  xPos.erase(std::unique(xPos.begin(), xPos.end()), xPos.end());
127  yPos.erase(std::unique(yPos.begin(), yPos.end()), yPos.end());
128  zPos.erase(std::unique(zPos.begin(), zPos.end()), zPos.end());
129  xPos.shrink_to_fit();
130  yPos.shrink_to_fit();
131  zPos.shrink_to_fit();
132  // get the number of bins
133  size_t nBinsX = xPos.size();
134  size_t nBinsY = yPos.size();
135  size_t nBinsZ = zPos.size();
136 
137  // get the minimum and maximum
138  auto minMaxX = std::minmax_element(xPos.begin(), xPos.end());
139  auto minMaxY = std::minmax_element(yPos.begin(), yPos.end());
140  auto minMaxZ = std::minmax_element(zPos.begin(), zPos.end());
141  // Create the axis for the grid
142  // get minima
143  double xMin = *minMaxX.first;
144  double yMin = *minMaxY.first;
145  double zMin = *minMaxZ.first;
146  // get maxima
147  double xMax = *minMaxX.second;
148  double yMax = *minMaxY.second;
149  double zMax = *minMaxZ.second;
150  // calculate maxima (add one last bin, because bin value always corresponds to
151  // left boundary)
152  double stepZ = std::fabs(zMax - zMin) / (nBinsZ - 1);
153  double stepY = std::fabs(yMax - yMin) / (nBinsY - 1);
154  double stepX = std::fabs(xMax - xMin) / (nBinsX - 1);
155  xMax += stepX;
156  yMax += stepY;
157  zMax += stepZ;
158 
159  detail::EquidistantAxis xAxis(xMin * lengthUnit, xMax * lengthUnit, nBinsX);
160  detail::EquidistantAxis yAxis(yMin * lengthUnit, yMax * lengthUnit, nBinsY);
161  detail::EquidistantAxis zAxis(zMin * lengthUnit, zMax * lengthUnit, nBinsZ);
162  // Create the grid
163  using Grid_t = detail::Grid<ActsVectorF<5>, detail::EquidistantAxis,
164  detail::EquidistantAxis, detail::EquidistantAxis>;
165  Grid_t grid(
166  std::make_tuple(std::move(xAxis), std::move(yAxis), std::move(zAxis)));
167 
168  // [3] Set the bField values
169  for (size_t i = 1; i <= nBinsX; ++i) {
170  for (size_t j = 1; j <= nBinsY; ++j) {
171  for (size_t k = 1; k <= nBinsZ; ++k) {
172  Grid_t::index_t indices = {{i, j, k}};
173  std::array<size_t, 3> nIndices = {
174  {xPos.size(), yPos.size(), zPos.size()}};
175  // std::vectors begin with 0 and we do not want the user needing to
176  // take underflow or overflow bins in account this is why we need to
177  // subtract by one
178  grid.atLocalBins(indices) = materialVector.at(
179  materialVectorToGridMapper({{i - 1, j - 1, k - 1}}, nIndices));
180  }
181  }
182  }
183  ActsVectorF<5> vec;
185  0., 0., 0.;
186  grid.setExteriorBins(vec);
187 
188  // [4] Create the transformation for the position
189  // map (x,y,z) -> (r,z)
190  auto transformPos = [](const Vector3D& pos) { return pos; };
191 
192  // [5] Create the mapper & BField Service
193  // create material mapping
194  return MaterialMapper<
195  detail::Grid<ActsVectorF<5>, detail::EquidistantAxis,
196  detail::EquidistantAxis, detail::EquidistantAxis>>(
197  transformPos, std::move(grid));
198 }