ATLAS Offline Software
Loading...
Searching...
No Matches
LayerMaterialRecord.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// LayerMaterialRecord.cxx, (c) ATLAS Detector software
8
10
15#include "TrkGeometry/Layer.h"
19#include "TrkSurfaces/Surface.h"
21
23 : m_layerThickness(0.),
24 m_binUtility(nullptr),
25 m_bins0(0),
26 m_bins1(0),
27 m_minFraction(0.),
28 m_steps(0),
29 m_pos(Amg::Vector3D(0., 0., 0.)),
30 m_emptyHitCase(false),
31 m_s(0.),
32 m_s_in_x0(0.),
33 m_s_in_l0(0.),
34 m_a(0.),
35 m_z(0.),
36 m_rho(0.),
38 // m_pos = Amg::Vector3D(0.,0.,0.);
39}
40
42 double thickness, const BinUtility* binutils, double minfraction,
44 : m_layerThickness(thickness),
45 m_binUtility(binutils ? binutils->clone() : nullptr),
46 m_bins0(binutils ? (binutils->max(0) + 1) : 1),
47 m_bins1(binutils && binutils->dimensions() > 1 ? (binutils->max(1) + 1)
48 : 1),
49 m_minFraction(minfraction),
50 m_steps(0),
51 m_pos(Amg::Vector3D(0., 0., 0.)),
52 m_emptyHitCase(false),
53 m_s(0.),
54 m_s_in_x0(0.),
55 m_s_in_l0(0.),
56 m_a(0.),
57 m_z(0.),
58 m_rho(0.),
59 m_assoc(assoc) {
60 // initialize for the run
61 const auto zeroedVectorDbl = std::vector<double>(m_bins0, 0.);
62 const auto zeroedVectorUInt = std::vector<unsigned int>(m_bins0, 0);
63 const auto zeroedVectorVector3D = std::vector<Amg::Vector3D>(m_bins0, m_pos);
64 using Element_t = std::map<unsigned int, double>;
65 const auto zeroedVectorElements =
66 std::vector<Element_t>(m_bins0, Element_t());
67 for (int ibin = 0; ibin < m_bins1; ++ibin) {
68 // run-related parameters
69 m_run_pos.push_back(zeroedVectorVector3D);
70 m_run_events.push_back(zeroedVectorUInt);
71 m_run_s.push_back(zeroedVectorDbl);
72 m_run_s_in_x0.push_back(zeroedVectorDbl);
73 m_run_s_in_l0.push_back(zeroedVectorDbl);
74 m_run_a.push_back(zeroedVectorDbl);
75 m_run_z.push_back(zeroedVectorDbl);
76 m_run_rho.push_back(zeroedVectorDbl);
77 m_run_elements.push_back(zeroedVectorElements);
78 }
79}
80
110
112 const Trk::LayerMaterialRecord& lmr) {
113 if (this != &lmr) {
115 delete m_binUtility;
116 m_binUtility = lmr.m_binUtility ? lmr.m_binUtility->clone() : nullptr;
117 m_bins0 = lmr.m_bins0;
118 m_bins1 = lmr.m_bins1;
120 m_assoc = lmr.m_assoc;
121 m_steps = lmr.m_steps;
122 m_pos = lmr.m_pos;
124 m_s = lmr.m_s;
125 m_s_in_x0 = lmr.m_s_in_x0;
126 m_s_in_l0 = lmr.m_s_in_l0;
127 m_a = lmr.m_a;
128 m_z = lmr.m_z;
129 m_rho = lmr.m_rho;
132 m_run_s = lmr.m_run_s;
135 m_run_pos = lmr.m_run_pos;
136 m_run_a = lmr.m_run_a;
137 m_run_z = lmr.m_run_z;
138 m_run_rho = lmr.m_run_rho;
140 // deal with the material
143 }
144 return (*this);
145}
146
148 // don't delete the material -> its given to the outside world
149 delete m_binUtility;
150}
151
153 double s,
154 const Trk::Material& mat) {
155 m_steps++;
156
157 m_s += s;
158 // path association method
159 m_pos += pos;
160 // path lenght updates
161 m_s_in_x0 += s / mat.X0;
162 m_s_in_l0 += s / mat.L0;
163 // effective rho, A, Z weithed by pathlength through it
164 m_rho += mat.rho * s;
165 m_a += mat.A * s * mat.rho;
166 m_z += mat.Z * s * mat.rho;
167
168 // record the composition - since this is mainly for hadronic interactions :
169 // weight by s/L0
170 MaterialComposition* mComposition = mat.composition;
171 if (mComposition) {
172 for (auto& it : (*mComposition)) {
173 // element identification
174 unsigned int Z = uchar2uint(it.first);
175 double fraction = uchar2dfrac(it.second);
176 // record the elements, let's weight the fractions in s/mat.L0
177 auto eIter = m_elements.find(Z);
178 if (eIter == m_elements.end())
179 m_elements[Z] = fraction * s / mat.L0;
180 else
181 m_elements[Z] += fraction * s / mat.L0;
182 }
183 }
184}
185
187 // just remember that you had an empty hit
188 m_emptyHitCase = true;
189 // take the position to increase the event counter by one
190 m_pos = pos;
191}
192
194 const Trk::Layer& lay, bool fullHit) {
195 Trk::AssociatedMaterial* fullHitMaterial = nullptr;
196 // empty hit scaling
197 if (m_emptyHitCase) {
198 // averge the hit positions
199 int rBin0 = m_binUtility ? m_binUtility->bin(m_pos, 0) : 0;
200 int rBin1 = (m_binUtility && m_binUtility->dimensions() > 1)
201 ? m_binUtility->bin(m_pos, 1)
202 : 0;
203 // simply increas the event counter
204 m_run_events[rBin1][rBin0]++;
205 // material hit collection
206 } else if (m_steps) {
207 // only if there was a single step in the event
208 Amg::Vector3D hitPosition(m_pos * 1. / (m_steps));
209 // get the correction factor depending on the layer type
210 double corrFactorInv = fabs(1. / lay.surfaceRepresentation().pathCorrection(
211 hitPosition, hitPosition));
212 // averge the hit positions
213 int rBin0 = m_binUtility ? m_binUtility->bin(hitPosition, 0) : 0;
214 int rBin1 = (m_binUtility && m_binUtility->dimensions() > 1)
215 ? m_binUtility->bin(hitPosition, 1)
216 : 0;
217
218 // event averaging
219 m_run_events[rBin1][rBin0]++;
220 m_run_s[rBin1][rBin0] += m_s;
221 m_run_pos[rBin1][rBin0] += hitPosition;
222 m_run_s_in_x0[rBin1][rBin0] += m_s_in_x0 * corrFactorInv;
223 m_run_s_in_l0[rBin1][rBin0] += m_s_in_l0 * corrFactorInv;
224 // a & z are normalised to rho
225 m_run_a[rBin1][rBin0] += m_a / m_rho;
226 m_run_z[rBin1][rBin0] += m_z / m_rho;
227 // rho is normalised to the layer thickness times corection factor
228 m_run_rho[rBin1][rBin0] += m_rho * corrFactorInv / m_layerThickness; // ST
229
230 // add to the run element table
231 for (auto& eIter : m_elements) {
232 // first normalize the element fraction
233 double nef = eIter.second * corrFactorInv / m_s_in_l0;
234 if (m_run_elements[rBin1][rBin0].find(eIter.first) ==
235 m_run_elements[rBin1][rBin0].end())
236 m_run_elements[rBin1][rBin0][eIter.first] = nef;
237 else
238 m_run_elements[rBin1][rBin0][eIter.first] += nef;
239 }
240
241 // just for validation purpose
242 if (fullHit) {
243 // average the material for the per event validation
244 double eventNorm = 1. / double(m_run_events[rBin1][rBin0]);
245
246 // normalize the value by number of recorded events - each event counts
247 // the same
248 double a = m_run_a[rBin1][rBin0] * eventNorm;
249 double z = m_run_z[rBin1][rBin0] * eventNorm;
250 double rho = m_run_rho[rBin1][rBin0] * eventNorm;
251
252 // the average s/X0 and s/L0 is the average over all events corrected by
253 // the incident angle
254 double s_in_x0 = m_run_s_in_x0[rBin1][rBin0] * eventNorm;
255 double s_in_l0 = m_run_s_in_l0[rBin1][rBin0] * eventNorm;
256
257 // condense to the layer thickness
258 double x0 = m_layerThickness / s_in_x0;
259 double l0 = m_layerThickness / s_in_l0;
260
262 fullHitMaterial = new Trk::AssociatedMaterial(
263 hitPosition, m_run_s[rBin1][rBin0] * eventNorm, x0, l0, a, z, rho,
264 corrFactorInv, lay.enclosingTrackingVolume(), &lay);
265 }
266 }
267
268 // reset event variables
269 m_emptyHitCase = false;
270 m_steps = 0;
271 m_pos = Amg::Vector3D(0., 0., 0.);
272 m_s = 0.;
273 m_s_in_x0 = 0.;
274 m_s_in_l0 = 0.;
275 m_a = 0.;
276 m_z = 0.;
277 m_rho = 0.;
278 m_elements.clear();
279
280 return fullHitMaterial;
281}
282
283void Trk::LayerMaterialRecord::finalizeRun(bool recordElements) {
285
286 for (int ibin1 = 0; ibin1 < m_bins1; ++ibin1) {
287 // create the vector first
289 matVector.reserve(m_bins0);
290 // loop over local 1 bins
291 for (int ibin0 = 0; ibin0 < m_bins0; ++ibin0) {
292 Trk::MaterialProperties* binMaterial = nullptr;
293 if (m_run_events[ibin1][ibin0]) {
294 // The event norm
295 double eventNorm = 1. / double(m_run_events[ibin1][ibin0]);
296
297 // normalize the value by number of recorded events - each event counts
298 // the same
299 m_run_a[ibin1][ibin0] *= eventNorm;
300 m_run_z[ibin1][ibin0] *= eventNorm;
301 m_run_rho[ibin1][ibin0] *= eventNorm;
302
303 // the average s/X0 and s/L0 is the average over all events corrected by
304 // the incident angle
305 m_run_s_in_x0[ibin1][ibin0] *= eventNorm;
306 m_run_s_in_l0[ibin1][ibin0] *= eventNorm;
307
308 // condense to the layer thickness
309 double x0 = m_layerThickness / m_run_s_in_x0[ibin1][ibin0];
310 double l0 = m_layerThickness / m_run_s_in_l0[ibin1][ibin0];
311
312 // prepare the material composition
313 Trk::MaterialComposition* matComposition = nullptr;
314 if (recordElements) {
315 // pre-loop to get a sample
316 double preTotalFraction = 0.;
317 std::map<unsigned int, double> binElements =
318 m_run_elements[ibin1][ibin0];
319 for (auto& peIter : binElements) {
320 // normalize the fraction to the number of events
321 peIter.second *= eventNorm;
322 preTotalFraction += peIter.second;
323 }
324 if (preTotalFraction == 0.) [[unlikely]]{
325 throw std::runtime_error("Trk::LayerMaterialRecord::finalizeRun: preTotalFraction is zero.");
326 }
327 // first loop to sort rescale
328 std::map<double, unsigned int> probabilityOrdered;
329 double totalFraction = 0.;
330 for (auto& eIter : binElements) {
331 // get the fraction
332 double eFraction = eIter.second / preTotalFraction;
333 if (eFraction < m_minFraction) continue;
334 probabilityOrdered[eIter.second] = eIter.first;
335 totalFraction += eIter.second;
336 }
337 if (totalFraction == 0.) [[unlikely]]{
338 throw std::runtime_error("Trk::LayerMaterialRecord::finalizeRun: totalFraction is zero.");
339 }
340 // second loop to fill the element fractions
341 std::vector<Trk::ElementFraction> elementFractions;
342 elementFractions.reserve(binElements.size());
343 for (auto& poEl : probabilityOrdered) {
344 double fracEl = poEl.first / totalFraction;
345 unsigned int fracEluChar = fracEl * UCHAR_MAX;
346 elementFractions.emplace_back(poEl.second, fracEluChar);
347 }
348 // reverse the order to have the one with the highest fraction first
349 std::reverse(elementFractions.begin(), elementFractions.end());
350 matComposition = new Trk::MaterialComposition(elementFractions);
351 }
352
353 Trk::Material material(x0, l0, m_run_a[ibin1][ibin0],
354 m_run_z[ibin1][ibin0], m_run_rho[ibin1][ibin0],
355 0., matComposition);
356
357 binMaterial = new Trk::MaterialProperties(material, m_layerThickness);
358 }
359 matVector.push_back(binMaterial);
360 }
361 m_associatedLayerMaterial.push_back(std::move(matVector));
362 }
363}
364
366 Trk::MaterialPropertiesMatrix::iterator matMatrixIter =
368 Trk::MaterialPropertiesMatrix::iterator matMatrixIterEnd =
370 for (; matMatrixIter != matMatrixIterEnd; ++matMatrixIter) {
371 // loop over the subsets
372 std::vector<const Trk::MaterialProperties*>::iterator matIter =
373 (*matMatrixIter).begin();
374 std::vector<const Trk::MaterialProperties*>::iterator matIterEnd =
375 (*matMatrixIter).end();
376 for (; matIter != matIterEnd; ++matIter) delete (*matIter);
377 }
379}
380
382 const MaterialPropertiesMatrix& materialMatrix) {
383 // clear the vector
385
386 Trk::MaterialPropertiesMatrix::const_iterator matMatrixIter =
387 materialMatrix.begin();
388 Trk::MaterialPropertiesMatrix::const_iterator matMatrixIterEnd =
389 materialMatrix.end();
390 for (; matMatrixIter != matMatrixIterEnd; ++matMatrixIter) {
392 // loop over the subsets
393 std::vector<const Trk::MaterialProperties*>::const_iterator matIter =
394 (*matMatrixIter).begin();
395 std::vector<const Trk::MaterialProperties*>::const_iterator matIterEnd =
396 (*matMatrixIter).end();
397 for (; matIter != matIterEnd; ++matIter) {
398 // test it
399 matProp.push_back(((*matIter) ? (*matIter)->clone() : nullptr));
400 }
401 // and now push back the vector
402 m_associatedLayerMaterial.push_back(std::move(matProp));
403 }
404}
static Double_t a
Eigen::Matrix< double, 3, 1 > Vector3D
#define max(a, b)
Definition cfImp.cxx:41
It is used in the Mapping process ( using MaterialSteps ), the validation and recostruction ( using M...
A generic symmetric BinUtility, for fully symmetric binning in terms of binning grid and binning type...
Definition BinUtility.h:39
BinUtility * clone() const
Implicit Constructor.
Definition BinUtility.h:120
Helper Class to record the material during the GeantinoNtupleMappingProcess.
int m_bins1
number of bins in coordinate 2
std::vector< std::vector< unsigned int > > m_run_events
LayerMaterialRecord()
Default Constructor.
std::vector< std::vector< double > > m_run_s_in_x0
double m_layerThickness
record the layerThickness
std::vector< std::vector< double > > m_run_s
LayerMaterialRecord & operator=(const LayerMaterialRecord &lmr)
Assignment operator.
std::map< unsigned int, double > m_elements
Amg::Vector3D m_pos
event related information
std::vector< std::vector< double > > m_run_a
MaterialAssociationType m_assoc
type of hit association
void finalizeRun(bool recordElements=true)
finalize the Run
AssociatedMaterial * finalizeEvent(const Trk::Layer &lay, bool fullHit=false)
finalize the Event
std::vector< std::vector< Amg::Vector3D > > m_run_pos
MaterialPropertiesMatrix m_associatedLayerMaterial
clear the material -> calls delete
BinUtility * m_binUtility
record the BinnedArray
std::vector< std::vector< std::map< unsigned int, double > > > m_run_elements
the final material properties
void clearMaterial()
copy from another vector
void associateGeantinoHit(const Amg::Vector3D &pos, double s, const Trk::Material &mat)
adding the information about the Geantino hit
void copyMaterial(const MaterialPropertiesMatrix &mat)
void associateEmptyHit(const Amg::Vector3D &pos)
adding the information about an empty hit scaling- particle crossed layer, but no mapping information
std::vector< std::vector< double > > m_run_s_in_l0
std::vector< std::vector< double > > m_run_z
double m_minFraction
minimum element fraction to be recorded
int m_bins0
number of bins in coordinate 1
std::vector< std::vector< double > > m_run_rho
Base Class for a Detector Layer in the Tracking realm.
Definition Layer.h:72
virtual const Surface & surfaceRepresentation() const =0
Transforms the layer into a Surface representation for extrapolation.
const TrackingVolume * enclosingTrackingVolume() const
get the confining TrackingVolume
Material with information about thickness of material.
A common object to be contained by.
Definition Material.h:117
virtual double pathCorrection(const Amg::Vector3D &pos, const Amg::Vector3D &mom) const
the pathCorrection for derived classes with thickness - it reflects if the direction projection is po...
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:140
Definition of ATLAS Math & Geometry primitives (Amg).
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the ATLAS eigen extensions are properly loaded.
@ z
global position (cartesian)
Definition ParamDefs.h:57
std::vector< const MaterialProperties * > MaterialPropertiesVector
Useful typedefs.
std::vector< std::vector< const MaterialProperties * > > MaterialPropertiesMatrix
void reverse(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of reverse for DataVector/List.
#define unlikely(x)