CbmRoot
Loading...
Searching...
No Matches
KfMaterialMap.cxx
Go to the documentation of this file.
1/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Sergey Gorbunov, Sergei Zharko [committer] */
4
5#include "KfMaterialMap.h"
6
8#include "KfSimd.h"
9
10#include <cmath>
11#include <iomanip>
12#include <sstream>
13#include <vector>
14
15#include <fmt/format.h>
16
19
20// ---------------------------------------------------------------------------------------------------------------------
21//
22MaterialMap::MaterialMap(int nBins, float xyMax, float zRef, float zMin, float zMax)
23 : fNbins(nBins)
24 , fXYmax(xyMax)
25 , fFactor(0.5 * fNbins / fXYmax)
26 , fZref(zRef)
27 , fZmin(zMin)
28 , fZmax(zMax)
29{
30 this->CheckConsistency();
31 fTable.resize(fNbins * fNbins);
32}
33
34// ---------------------------------------------------------------------------------------------------------------------
35//
36void MaterialMap::Add(const MaterialMap& other, float zTarg)
37{
38 // The function allows to add a material layer either from the left or from the right to the station
39 // NOTE: A symmetry of x-y is assumed
40 constexpr int nRays{3}; // Number of rays in a bin in a dimension
41 const bool bRadialRays{!std::isnan(zTarg)}; // Are rays radial (true, coming from target) or parallel (false)?
42 const auto scaleFactor{bRadialRays ? ((other.fZref - zTarg) / (this->fZref - zTarg)) : 1.F};
43 const auto binSize{2.F * scaleFactor * this->fXYmax / this->fNbins}; // Size of each bin dimension [cm]
44 const auto stepSize{binSize / static_cast<float>(nRays)}; // Step between two neighboring rays [cm]
45
46 // The coordinates of the first ray intersection with the other material layer [cm]
47 float yBinOther{-this->fXYmax * scaleFactor + stepSize * 0.5F};
48
49 // Loop over bins of the active (this)
50 for (int iBinY{0}; iBinY < this->fNbins; ++iBinY) {
51 float xBinOther{-this->fXYmax * scaleFactor + stepSize * 0.5F};
52 for (int iBinX{0}; iBinX < this->fNbins; ++iBinX) {
53 // Collect material using ray shooting
54 float avgThickness{0}; // Collected average thickness
55 for (int iRayY{0}; iRayY < nRays; ++iRayY) {
56 for (int iRayX{0}; iRayX < nRays; ++iRayX) {
57 avgThickness += other.GetThicknessX0(xBinOther + iRayX * stepSize, yBinOther + iRayY * stepSize);
58 }
59 }
60 this->fTable[iBinX + this->fNbins * iBinY] += (avgThickness / (nRays * nRays));
61 xBinOther += binSize;
62 }
63 yBinOther += binSize;
64 }
65 this->fZmin = std::min(this->fZmin, other.fZmin);
66 this->fZmax = std::max(this->fZmax, other.fZmax);
67}
68
69// ---------------------------------------------------------------------------------------------------------------------
70//
71int MaterialMap::GetBin(float x, float y) const
72{
73 int i{static_cast<int>((x + fXYmax) * fFactor)};
74 int j{static_cast<int>((y + fXYmax) * fFactor)};
75 if (i < 0 || j < 0 || i >= fNbins || j >= fNbins) {
76 return -1;
77 }
78 return i + j * fNbins;
79}
80
81// ---------------------------------------------------------------------------------------------------------------------
82//
83void MaterialMap::Rebin(int nGroups)
84{
85 if (nGroups < 1 && nGroups > fNbins) {
86 int nGroupsSet{nGroups};
87 nGroups = std::clamp(nGroups, 1, fNbins);
88 LOG(warn) << "kf::MaterialMap::Rebin(): incorrect input parameter nGroups = " << nGroupsSet << " is set to "
89 << nGroups;
90 }
91
92 int nBinsNew = static_cast<int>(static_cast<bool>(fNbins % nGroups)) + fNbins / nGroups;
93 std::vector<float> table(nBinsNew * nBinsNew);
94 for (int iX{0}; iX < nBinsNew; ++iX) {
95 for (int iY{0}; iY < nBinsNew; ++iY) {
96 float value{0.F};
97 int nEntries{0};
98 int iOldXmin{iX * nGroups};
99 int iOldXmax{std::max((iX + 1) * nGroups, fNbins)};
100 int iOldYmin{iY * nGroups};
101 int iOldYmax{std::max((iY + 1) * nGroups, fNbins)};
102 for (int iOldX{iOldXmin}; iOldX < iOldXmax; ++iOldX) {
103 for (int iOldY{iOldYmin}; iOldY < iOldYmax; ++iOldY) {
104 value += fTable[iOldX + fNbins * iOldY];
105 ++nEntries;
106 }
107 }
108 table[iX + nBinsNew * iY] = value / nEntries;
109 }
110 }
111 fTable = std::move(table);
112 fFactor = fFactor / fNbins * nBinsNew;
113 fNbins = nBinsNew;
114}
115
116// ---------------------------------------------------------------------------------------------------------------------
117//
118std::string MaterialMap::ToString(int indentLevel, int verbose) const
119{
120 using fmt::format;
121 using std::setw;
122 std::stringstream msg;
123 if (verbose > 0) {
124 constexpr char indentCh = '\t';
125 std::string indent(indentLevel, indentCh);
126 msg << format("zRef = {:<12} cm, range [{:<12}, {:<12}] cm, nBins = {:<8}, XYmax = {:<12} cm", fZref, fZmin, fZmax,
127 fNbins, fXYmax);
128 if (verbose > 1) {
129 msg << indent << indentCh << "\nContent(rebinned to 10 bins):\n";
130 msg.precision(3);
131 auto mapTmp{*this};
132 mapTmp.Rebin(fNbins / 10);
133 msg << indent << indentCh << setw(15) << "y [cm] \\ x [cm]" << ' ';
134 for (int iX{0}; iX < mapTmp.fNbins; ++iX) {
135 float xRef{-mapTmp.fXYmax + (mapTmp.fXYmax * (2 * iX + 1)) / mapTmp.fNbins};
136 msg << setw(10) << xRef << ' ';
137 }
138 msg << '\n';
139 for (int iY{0}; iY < mapTmp.fNbins; ++iY) {
140 float yRef{-mapTmp.fXYmax + (mapTmp.fXYmax * (2 * iY + 1)) / mapTmp.fNbins};
141 msg << indent << indentCh << setw(15) << yRef << ' ';
142 for (int iX{0}; iX < mapTmp.fNbins; ++iX) {
143 msg << setw(10) << mapTmp.fTable[iX + mapTmp.fNbins * iY] << ' ';
144 }
145 msg << '\n';
146 }
147 }
148 }
149 return msg.str();
150}
151
152// ---------------------------------------------------------------------------------------------------------------------
153//
155{
156 if (fNbins < 1) {
157 std::stringstream aStream;
158 aStream << "MaterialMap: object cannot be initialized with non-positive nBins = " << fNbins;
159 throw std::logic_error(aStream.str());
160 }
161
162 if (fXYmax < 0.) {
163 std::stringstream aStream;
164 aStream << "MaterialMap: object cannot be initialized with non-positive XYmax = " << fXYmax << " [cm]";
165 throw std::logic_error(aStream.str());
166 }
167
168 if (!((fZmin <= fZref) && (fZref <= fZmax))) {
169 std::stringstream aStream;
170 aStream << "MaterialMap: object cannot be initialized with inconsistent Z: min " << fZmin << " ref " << fZref
171 << " max " << fZmax << " [cm]";
172 throw std::logic_error(aStream.str());
173 }
174}
Implementation selection for the SIMD utilities (VS or pseudo)
MaterialMap()=default
Default constructor.
A map of station thickness in units of radiation length (X0) to the specific point in XY plane.
std::vector< float > fTable
Material budget table.
void Rebin(int factor)
Reduces number of bins by a given factor.
float fFactor
Util. var. for the conversion of point coordinates to row/column id.
int fNbins
Number of rows (== N columns) in the material budget table.
float fXYmax
Size of the station in x and y dimensions [cm].
float fZmax
Minimal Z of the collected material [cm].
float fZref
Reference Z of the collected material [cm].
MaterialMap()=default
Default constructor.
int GetBin(float x, float y) const
Gets bin index for (x,y). Returns -1 when outside of the map.
I GetThicknessX0(const I &x, const I &y) const
Gets material thickness in units of radiational length X0.
float fZmin
Minimal Z of the collected material [cm].
void Add(const MaterialMap &other, float zTarg=defs::Undef< float >)
Adds material layer.
std::string ToString(int indentLevel=0, int verbose=1) const
String representation of the object.
void CheckConsistency() const
Checks the object consistency.