ATLAS Offline Software
ElectronMaterialMixtureConvolution.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
18 
20 #include "CxxUtils/inline_hints.h"
21 //
22 #include "TrkGeometry/Layer.h"
25 
26 #include <array>
27 namespace {
28 
30 inline void
31 dummyCacheElement(GsfMaterial::Combined& elem)
32 {
33  elem.numEntries = 1;
34  elem.deltaPs[0] = 0;
35  elem.parameters[0] = AmgVector(5)::Zero();
36  elem.covariances[0] = AmgSymMatrix(5)::Zero();
37 }
38 
39 // Avoid out-of-line Eigen calls
41 inline void
42 updateCacheElement(GsfMaterial::Combined& updated,
43  size_t index,
44  const AmgVector(5) & parameters,
45  const AmgSymMatrix(5) * covariance)
46 {
47  updated.parameters[index] = parameters;
48  if (covariance) {
49  updated.covariances[index] += *covariance;
50  } else {
51  updated.covariances[index].setZero();
52  }
53 }
54 
55 bool
56 updateP(double& qOverP, double deltaP)
57 {
58  double p = 1. / std::abs(qOverP);
59  p += deltaP;
60  if (p <= 0.) {
61  return false;
62  }
63  qOverP = qOverP > 0. ? 1. / p : -1. / p;
64  return true;
65 }
66 
67 std::pair<const Trk::MaterialProperties*, double>
68 getMaterialProperties(const Trk::TrackParameters* trackParameters,
69  const Trk::Layer& layer)
70 {
71 
72  const Trk::MaterialProperties* materialProperties(nullptr);
73  double pathCorrection(0.);
74 
75  // Check that the material properties have been defined - if not define them
76  // from the layer information
77  materialProperties = materialProperties
78  ? materialProperties
79  : layer.fullUpdateMaterialProperties(*trackParameters);
80  // Bail out if still no material properties can be found
81  if (!materialProperties) {
82  return { nullptr, 0 };
83  }
84  // Define the path correction
85  pathCorrection =
86  pathCorrection > 0.
87  ? pathCorrection
88  : layer.surfaceRepresentation().pathCorrection(
89  trackParameters->position(), trackParameters->momentum());
90 
91  // The pathlength ( in mm ) is the path correction * the thickness of the
92  // material
93  const double pathLength = pathCorrection * materialProperties->thickness();
94  return { materialProperties, pathLength };
95 }
96 
97 Trk::MultiComponentState createMergedState(const GSFUtils::MergeArray& merges,
98  std::vector<GsfMaterial::Combined>& caches,
99  const std::vector<std::pair<size_t, size_t>>& indices,
100  const Trk::MultiComponentState& inputState){
101 
103  size_t numComponents = indices.size();
104  // Gather the merges we need
105  std::vector<char> isMerged(numComponents, 0);
106  // Merge components "From" to components "To"
107  const int returnedMerges = merges.size();
108  for (int i = 0; i < returnedMerges; ++i) {
109  const int mini = merges[i].To;
110  const int minj = merges[i].From;
111  // Get the first TP
112  const size_t stateIndex = indices[mini].first;
113  const size_t materialIndex = indices[mini].second;
114  // Copy weight and first parameters as they are needed later on
115  // for updating the covariance
116  const AmgVector(5) firstParameters =
117  caches[stateIndex].parameters[materialIndex];
118  const double firstWeight = caches[stateIndex].weights[materialIndex];
119  // Get the second TP
120  const size_t stateIndex2 = indices[minj].first;
121  const size_t materialIndex2 = indices[minj].second;
122  // Set as merged
123  isMerged[minj] = 1;
124  // Update first parameters and weight
125  Trk::MultiComponentStateCombiner::combineParametersWithWeight(
126  caches[stateIndex].parameters[materialIndex],
127  caches[stateIndex].weights[materialIndex],
128  caches[stateIndex2].parameters[materialIndex2],
129  caches[stateIndex2].weights[materialIndex2]);
130  // Update covariance
131  Trk::MultiComponentStateCombiner::combineCovWithWeight(
132  firstParameters, caches[stateIndex].covariances[materialIndex],
133  firstWeight, caches[stateIndex2].parameters[materialIndex2],
134  caches[stateIndex2].covariances[materialIndex2],
135  caches[stateIndex2].weights[materialIndex2]);
136  // Reset 2nd parameters values just for clarity
137  caches[stateIndex2].parameters[materialIndex2].setZero();
138  caches[stateIndex2].covariances[materialIndex2].setZero();
139  }
140 
141  // Loop over remaining unmerged components
142  for (size_t i(0); i < numComponents; ++i) {
143  if (isMerged[i]) {
144  continue;
145  }
146  // Build the TP
147  const size_t stateIndex = indices[i].first;
148  const size_t materialIndex = indices[i].second;
149  AmgVector(5)& stateVector =
150  caches[stateIndex].parameters[materialIndex];
151  AmgSymMatrix(5)& measuredCov =
152  caches[stateIndex].covariances[materialIndex];
153 
154  std::unique_ptr<Trk::TrackParameters> updatedTrackParameters =
155  inputState[stateIndex]
156  .params->associatedSurface()
157  .createUniqueTrackParameters(
158  stateVector[Trk::loc1], stateVector[Trk::loc2],
159  stateVector[Trk::phi], stateVector[Trk::theta],
160  stateVector[Trk::qOverP], measuredCov);
161 
162  const double updatedWeight = caches[stateIndex].weights[materialIndex];
163 
164  assemblerCache.multiComponentState.push_back(
165  {std::move(updatedTrackParameters), updatedWeight});
166  assemblerCache.validWeightSum += updatedWeight;
167  }
169  std::move(assemblerCache));
170 }
171 } // end of anonymous namespace
172 
174  const std::string& type,
175  const std::string& name,
176  const IInterface* parent)
178 {
179  declareInterface<IMaterialMixtureConvolution>(this);
180 }
181 
183 
186 {
187  if (m_maximumNumberOfComponents > GSFConstants::maxNumberofStateComponents) {
188  ATH_MSG_FATAL("Requested MaximumNumberOfComponents > "
190  return StatusCode::FAILURE;
191  }
192 
193  m_materialEffects = std::make_unique<ElectronCombinedMaterialEffects>(
194  m_parameterisationFileName, m_parameterisationFileNameHighX0);
195  return StatusCode::SUCCESS;
196 }
197 
198 /* ==========================================
199  Update with full material effects
200  ========================================== */
203  std::vector<GsfMaterial::Combined>& caches,
204  const Trk::MultiComponentState& multiComponentState,
205  const Trk::Layer& layer,
206  Trk::PropDirection direction) const
207 {
208  const double updateFactor = 1.0;
209  Trk::MultiComponentState updatedMergedState = update(
210  caches, multiComponentState, layer, direction, updateFactor);
211 
212  if (updatedMergedState.empty()) {
213  return {};
214  }
216  return updatedMergedState;
217 }
218 
219 /* ==========================================
220  Update with pre-update material effects
221 ========================================== */
224  std::vector<GsfMaterial::Combined>& caches,
225  const Trk::MultiComponentState& multiComponentState,
226  const Trk::Layer& layer,
227  Trk::PropDirection direction) const
228 {
229  const double updateFactor =
230  layer.preUpdateMaterialFactor(*multiComponentState.front().params, direction);
231 
232  Trk::MultiComponentState updatedMergedState = update(caches,
233  multiComponentState,
234  layer,
235  direction,
236  updateFactor);
237  if (updatedMergedState.empty()) {
238  return {};
239  }
241  return updatedMergedState;
242 }
243 
244 /* ==========================================
245  Update with post-update material effects
246  ========================================== */
249  std::vector<GsfMaterial::Combined>& caches,
250  const Trk::MultiComponentState& multiComponentState,
251  const Trk::Layer& layer,
252  Trk::PropDirection direction) const
253 {
254  const double updateFactor = layer.postUpdateMaterialFactor(
255  *multiComponentState.front().params, direction);
256 
257  Trk::MultiComponentState updatedMergedState =
258  update(caches, multiComponentState, layer, direction, updateFactor);
259 
260  if (updatedMergedState.empty()) {
261  return {};
262  }
264  return updatedMergedState;
265 }
266 
269  std::vector<GsfMaterial::Combined>& caches,
270  const Trk::MultiComponentState& inputState,
271  const Trk::Layer& layer,
272  Trk::PropDirection direction,
273  double updateFactor) const
274 {
275 
276  // Check the multi-component state is populated
277  if (inputState.empty()) {
278  return {};
279  }
280  if (updateFactor < 0.01) {
281  // Bail out as factor is too small to bother about
282  return {};
283  }
284  caches.resize(inputState.size());
285 
286  // Fill cache and work out how many final components there should be
287  size_t numComponents(0);
288  for (size_t i(0); i < inputState.size(); ++i) {
289  const AmgSymMatrix(5)* measuredCov = inputState[i].params->covariance();
290  // If the momentum is too dont apply material effects
291  if (inputState[i].params->momentum().mag() <= 250. * Gaudi::Units::MeV) {
292  dummyCacheElement(caches[i]);
293  updateCacheElement(caches[i], 0, inputState[i].params->parameters(), measuredCov);
294  caches[i].weights[0] = inputState[i].weight;
295  numComponents += caches[i].numEntries;
296  continue;
297  }
298  // Get the material effects and store them in the cache
299  std::pair<const Trk::MaterialProperties*, double> matPropPair =
300  getMaterialProperties(inputState[i].params.get(), layer);
301 
302  if (!matPropPair.first) {
303  dummyCacheElement(caches[i]);
304  updateCacheElement(caches[i], 0, inputState[i].params->parameters(), measuredCov);
305  caches[i].weights[0] = inputState[i].weight;
306  numComponents += caches[i].numEntries;
307  continue;
308  }
309  // Now we can compute/apply actual material effects
310  // Apply the update factor
311  matPropPair.second *= updateFactor;
312  m_materialEffects->compute(caches[i],
313  inputState[i],
314  *matPropPair.first,
315  matPropPair.second,
316  direction);
317 
318  // Apply material effects to input state and store results in cache
319  // We have i material caches , one for each input state.
320  // Each cache has j entries. They correspond to each
321  // Gausian used to describe the Bethe Heitler.
322  for (size_t j(0); j < caches[i].numEntries; ++j) {
323  updateCacheElement(caches[i], j, inputState[i].params->parameters(), measuredCov);
324  // Adjust q/p of the (delta) Parameters
325  // make sure update is good.
326  if (!updateP(caches[i].parameters[j][Trk::qOverP],
327  caches[i].deltaPs[j])) {
328  ATH_MSG_ERROR("Cannot update state vector momentum!!!");
329  return {};
330  }
331  // Store component weight
332  caches[i].weights[j] *= inputState[i].weight;
333  // Ensure weight of component is not too small to save us from potential
334  // FPE's Value. Weights are double so the min of float should
335  // be small enough and should be handled
336  if (caches[i].weights[j] < std::numeric_limits<float>::min()) {
337  caches[i].weights[j] = std::numeric_limits<float>::min();
338  }
339  }
340  numComponents += caches[i].numEntries;
341  } // End of loop filling the cache
342 
343  // Fill information for calculating which components to merge
344  // In addition scan all components for covariance matrices.
345  // If one component is missing its error matrix,
346  // component reduction is impossible.
347  //
348  bool componentWithoutMeasurement = false;
349  // keep track of the state component and material effects indices
350  // Effectively here we have M state X N Material effects
351  // MXN components.
352  std::vector<std::pair<size_t, size_t>> indices{};
353  indices.resize(numComponents);
354  GSFUtils::Component1DArray componentsArray(numComponents);
355  size_t k(0);
356  for (size_t i(0); i < inputState.size(); ++i) {
357  for (size_t j(0); j < caches[i].numEntries; ++j) {
358  const AmgSymMatrix(5)* measuredCov = inputState[i].params->covariance();
359  // Fill in infomation
360  const double cov =
361  measuredCov ? caches[i].covariances[j](Trk::qOverP, Trk::qOverP)
362  : -1.;
363  if (!measuredCov) {
364  componentWithoutMeasurement = true;
365  }
366  componentsArray[k].mean = caches[i].parameters[j][Trk::qOverP];
367  componentsArray[k].cov = cov;
368  componentsArray[k].invCov = cov > 0 ? 1. / cov : 1e10;
369  componentsArray[k].weight = caches[i].weights[j];
370  indices[k] = {i, j};
371  ++k;
372  }
373  }
374 
375  // fallback if we have a component without measurement
376  if (componentWithoutMeasurement) {
377  auto* result = std::max_element(
378  componentsArray.begin(), componentsArray.end(),
379  [](const auto& a, const auto& b) { return a.weight < b.weight; });
380  auto index = std::distance(componentsArray.begin(), result);
381  const size_t stateIndex = indices[index].first;
382  const size_t materialIndex = indices[index].second;
383 
384  AmgVector(5)& updatedStateVector = caches[stateIndex].parameters[materialIndex];
385  const AmgSymMatrix(5)* measuredCov = inputState[stateIndex].params->covariance();
386  std::optional<AmgSymMatrix(5)> updatedCovariance = std::nullopt;
387  if (measuredCov && caches[stateIndex].covariances.size() > materialIndex) {
388  updatedCovariance =
389  AmgSymMatrix(5)(caches[stateIndex].covariances[materialIndex]);
390  }
391  std::unique_ptr<Trk::TrackParameters> updatedTrackParameters =
392  inputState[stateIndex]
393  .params->associatedSurface()
395  updatedStateVector[Trk::loc1], updatedStateVector[Trk::loc2],
396  updatedStateVector[Trk::phi], updatedStateVector[Trk::theta],
397  updatedStateVector[Trk::qOverP], std::move(updatedCovariance));
398 
399  Trk::ComponentParameters dummyCompParams = {
400  std::move(updatedTrackParameters), 1.};
401  Trk::MultiComponentState returnMultiState;
402  returnMultiState.push_back(std::move(dummyCompParams));
403  return returnMultiState;
404  }
405 
406  //Create the state to rerurn accounting for any needed merges.
407  GSFUtils::MergeArray merges;
408  if (numComponents > m_maximumNumberOfComponents) {
409  merges = findMerges(std::move(componentsArray), m_maximumNumberOfComponents);
410  }
411  auto mergedState = createMergedState(merges, caches, indices, inputState);
412 
413  if (mergedState.size() > m_maximumNumberOfComponents) {
414  ATH_MSG_ERROR("Merging failed, target size: " << m_maximumNumberOfComponents
415  << " final size: "
416  << mergedState.size());
417  }
418  return mergedState;
419 }
420 
Trk::ElectronMaterialMixtureConvolution::initialize
virtual StatusCode initialize() override final
Convolution with full material properties.
Definition: ElectronMaterialMixtureConvolution.cxx:185
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
MultiComponentStateCombiner.h
inline_hints.h
get_generator_info.result
result
Definition: get_generator_info.py:21
Trk::MultiComponentStateAssembler::assembledState
MultiComponentState assembledState(MultiComponentStateAssembler::Cache &&cache)
Method to return the cached state object - it performs a reweighting before returning the object base...
Definition: MultiComponentStateAssembler.cxx:120
PerigeeSurface.h
MaterialProperties.h
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
index
Definition: index.py:1
Trk::ParametersBase::associatedSurface
virtual const Surface & associatedSurface() const override=0
Access to the Surface associated to the Parameters.
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
Trk::indices
std::pair< long int, long int > indices
Definition: AlSymMatBase.h:24
GsfMaterial::Combined::parameters
std::array< AmgVector(5), GSFConstants::maxNumberofMatComponents > parameters
Definition: GsfMaterial.h:56
python.SystemOfUnits.second
float second
Definition: SystemOfUnits.py:135
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:200
python.getProblemFolderFromLogs.elem
elem
Definition: getProblemFolderFromLogs.py:90
InDetSecVtxTruthMatchUtils::isMerged
bool isMerged(int matchInfo)
Definition: InDetSecVtxTruthMatchTool.h:79
Trk::loc2
@ loc2
generic first and second local coordinate
Definition: ParamDefs.h:35
Layer.h
ElectronMaterialMixtureConvolution.h
Class description for convolution of GSF material mixture.
Trk::MultiComponentStateAssembler::Cache
Definition: MultiComponentStateAssembler.h:35
InDetAccessor::qOverP
@ qOverP
perigee
Definition: InDetAccessor.h:35
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
GSFUtils::MergeArray
std::vector< Merge > MergeArray
Definition: KLGaussianMixtureReduction.h:47
Trk::ElectronMaterialMixtureConvolution::~ElectronMaterialMixtureConvolution
virtual ~ElectronMaterialMixtureConvolution()
AlgTool initialise method.
AmgSymMatrix
#define AmgSymMatrix(dim)
Definition: EventPrimitives.h:50
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
python.SystemOfUnits.MeV
float MeV
Definition: SystemOfUnits.py:172
Trk::MultiComponentStateCombiner::combineCovWithWeight
void combineCovWithWeight(const AmgVector(5) &firstParameters, AmgSymMatrix(5) &firstMeasuredCov, const double firstWeight, const AmgVector(5) &secondParameters, const AmgSymMatrix(5) &secondMeasuredCov, const double secondWeight)
Combine cov matrices based on their relevant weights.
Definition: MultiComponentStateCombiner.cxx:227
GSFConstants::maxNumberofStateComponents
constexpr int8_t maxNumberofStateComponents
The state is described by N Gaussian components The Beth Heitler Material effect are also described b...
Definition: GsfConstants.h:43
Trk::AmgSymMatrix
AmgSymMatrix(5) &GXFTrackState
Definition: GXFTrackState.h:156
MultiComponentStateAssembler.h
Trk::PropDirection
PropDirection
Definition: PropDirection.h:19
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
Trk::Surface::createUniqueTrackParameters
virtual ChargedTrackParametersUniquePtr createUniqueTrackParameters(double l1, double l2, double phi, double theat, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const =0
Use the Surface as a ParametersBase constructor, from local parameters - charged.
ATH_FLATTEN
#define ATH_FLATTEN
Definition: inline_hints.h:52
Trk::theta
@ theta
Definition: ParamDefs.h:66
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
AmgVector
AmgVector(4) T2BSTrackFilterTool
Definition: T2BSTrackFilterTool.cxx:114
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Trk::MultiComponentState
std::vector< ComponentParameters > MultiComponentState
Definition: ComponentParameters.h:27
Trk::ParametersBase
Definition: ParametersBase.h:55
Trk::ElectronMaterialMixtureConvolution::postUpdate
virtual MultiComponentState postUpdate(std::vector< GsfMaterial::Combined > &, const MultiComponentState &, const Layer &, PropDirection direction=anyDirection) const override final
The particle hypothesis we implement material effects for.
Definition: ElectronMaterialMixtureConvolution.cxx:248
GsfMaterial::Combined
Helper struct for combined material effects, multicomponent description.
Definition: GsfMaterial.h:49
Trk::ElectronMaterialMixtureConvolution::preUpdate
virtual MultiComponentState preUpdate(std::vector< GsfMaterial::Combined > &, const MultiComponentState &, const Layer &, PropDirection direction=anyDirection) const override final
Convolution with post-measurement-update material properties.
Definition: ElectronMaterialMixtureConvolution.cxx:223
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
Trk::MultiComponentStateCombiner::combineParametersWithWeight
void combineParametersWithWeight(AmgVector(5) &firstParameters, double &firstWeight, const AmgVector(5) &secondParameters, const double secondWeight)
Combine parameters based on their relevant weigths.
Definition: MultiComponentStateCombiner.cxx:201
Trk::MultiComponentStateHelpers::renormaliseState
void renormaliseState(MultiComponentState &, double norm=1)
Performing renormalisation of total state weighting to one.
Definition: ComponentParameters.cxx:80
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
GSFUtils::AlignedDynArray::begin
iterator begin() noexcept
iterator pointing to the first element
GSFUtils::AlignedDynArray::end
iterator end() noexcept
iterator pointing to the past-the-end element
weights
Definition: herwig7_interface.h:38
Trk::ComponentParameters
Definition: ComponentParameters.h:22
GSFUtils::findMerges
MergeArray findMerges(Component1DArray &&componentsIn, const int reducedSize)
Return which components need to be merged.
Definition: KLGaussianMixtureReduction.cxx:305
KLGaussianMixtureReduction.h
Utilities to facilitate the calculation of the KL divergence/distance between components of the mixtu...
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
ComponentParameters.h
Definition of component parameters for use in a mixture of many components. In this regime each track...
DeMoScan.index
string index
Definition: DeMoScan.py:362
Trk::MaterialProperties
Definition: MaterialProperties.h:40
a
TList * a
Definition: liststreamerinfos.cxx:10
Trk::MultiComponentStateAssembler::Cache::multiComponentState
Trk::MultiComponentState multiComponentState
Definition: MultiComponentStateAssembler.h:39
DeMoScan.first
bool first
Definition: DeMoScan.py:534
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:67
GsfMaterial::Combined::covariances
std::array< AmgSymMatrix(5), GSFConstants::maxNumberofMatComponents > covariances
Definition: GsfMaterial.h:60
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
GsfConstants.h
Trk::phi
@ phi
Definition: ParamDefs.h:75
PowhegControl_ttFCNC_NLO.params
params
Definition: PowhegControl_ttFCNC_NLO.py:226
AthAlgTool
Definition: AthAlgTool.h:26
Trk::loc1
@ loc1
Definition: ParamDefs.h:34
Trk::MultiComponentStateAssembler::Cache::validWeightSum
double validWeightSum
Definition: MultiComponentStateAssembler.h:40
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
Trk::ElectronMaterialMixtureConvolution::update
virtual MultiComponentState update(std::vector< GsfMaterial::Combined > &, const MultiComponentState &, const Layer &, PropDirection direction=anyDirection) const override final
Convolution with pre-measurement-update material properties.
Definition: ElectronMaterialMixtureConvolution.cxx:202
Trk::ElectronMaterialMixtureConvolution::ElectronMaterialMixtureConvolution
ElectronMaterialMixtureConvolution(const std::string &, const std::string &, const IInterface *)
Destructor.
Definition: ElectronMaterialMixtureConvolution.cxx:173
fitman.k
k
Definition: fitman.py:528
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
Trk::Layer
Definition: Layer.h:72
GSFUtils::AlignedDynArray
A wrapper around std::aligned_alloc.
Definition: AlignedDynArray.h:30