Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EDM4hepUtil.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EDM4hepUtil.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 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 
22 
23 #include "edm4hep/TrackState.h"
24 
25 namespace ActsExamples {
26 
28  const edm4hep::MCParticle& from, const MapParticleIdFrom& particleMapper) {
29  ActsFatras::Barcode particleId = particleMapper(from);
30 
31  ActsFatras::Particle to(particleId,
32  static_cast<Acts::PdgParticle>(from.getPDG()),
33  from.getCharge() * Acts::UnitConstants::e,
34  from.getMass() * Acts::UnitConstants::GeV);
35 
36  // TODO do we have that in EDM4hep?
37  // particle.setProcess(static_cast<ActsFatras::ProcessType>(data.process));
38 
39  to.setPosition4(from.getVertex()[0] * Acts::UnitConstants::mm,
40  from.getVertex()[1] * Acts::UnitConstants::mm,
41  from.getVertex()[2] * Acts::UnitConstants::mm,
42  from.getTime() * Acts::UnitConstants::ns);
43 
44  // Only used for direction; normalization/units do not matter
45  to.setDirection(from.getMomentum()[0], from.getMomentum()[1],
46  from.getMomentum()[2]);
47 
48  to.setAbsoluteMomentum(std::hypot(from.getMomentum()[0],
49  from.getMomentum()[1],
50  from.getMomentum()[2]) *
52 
53  return to;
54 }
55 
57  edm4hep::MutableMCParticle to) {
58  // TODO what about particleId?
59 
60  to.setPDG(from.pdg());
61  to.setCharge(from.charge() / Acts::UnitConstants::e);
62  to.setMass(from.mass() / Acts::UnitConstants::GeV);
63  to.setVertex({from.position().x(), from.position().y(), from.position().z()});
64  to.setMomentum({static_cast<float>(from.fourMomentum().x()),
65  static_cast<float>(from.fourMomentum().y()),
66  static_cast<float>(from.fourMomentum().z())});
67 }
68 
70  const edm4hep::SimTrackerHit& from, const MapParticleIdFrom& particleMapper,
71  const MapGeometryIdFrom& geometryMapper) {
72  ActsFatras::Barcode particleId = particleMapper(from.getMCParticle());
73  Acts::GeometryIdentifier geometryId = geometryMapper(from.getCellID());
74 
75  const auto mass = from.getMCParticle().getMass();
77  from.getMomentum().x * Acts::UnitConstants::GeV,
78  from.getMomentum().y * Acts::UnitConstants::GeV,
79  from.getMomentum().z * Acts::UnitConstants::GeV,
80  };
81  const auto energy = std::hypot(momentum.norm(), mass);
82 
84  from.getPosition().x * Acts::UnitConstants::mm,
85  from.getPosition().y * Acts::UnitConstants::mm,
86  from.getPosition().z * Acts::UnitConstants::mm,
87  from.getTime() * Acts::UnitConstants::ns,
88  };
89 
91  momentum.x(),
92  momentum.y(),
93  momentum.z(),
94  energy,
95  };
96 
97  // TODO no EDM4hep equivalent?
101  0 * Acts::UnitConstants::GeV, // sth.getEDep()
102  };
103 
104  // TODO no EDM4hep equivalent?
105  int32_t index = -1;
106 
107  return ActsFatras::Hit(geometryId, particleId, pos4, mom4, mom4 + delta4,
108  index);
109 }
110 
112  edm4hep::MutableSimTrackerHit to,
113  const MapParticleIdTo& particleMapper,
114  const MapGeometryIdTo& geometryMapper) {
115  const Acts::Vector4& globalPos4 = from.fourPosition();
116  const Acts::Vector4& momentum4Before = from.momentum4Before();
117  const auto delta4 = from.momentum4After() - momentum4Before;
118 
119  if (particleMapper) {
120  to.setMCParticle(particleMapper(from.particleId()));
121  }
122 
123  if (geometryMapper) {
124  // TODO what about the digitization?
125  to.setCellID(geometryMapper(from.geometryId()));
126  }
127 
128  to.setTime(globalPos4[Acts::eTime] / Acts::UnitConstants::ns);
129 
130  to.setPosition({
131  globalPos4[Acts::ePos0] / Acts::UnitConstants::mm,
132  globalPos4[Acts::ePos1] / Acts::UnitConstants::mm,
133  globalPos4[Acts::ePos2] / Acts::UnitConstants::mm,
134  });
135 
136  to.setMomentum({
137  static_cast<float>(momentum4Before[Acts::eMom0] /
139  static_cast<float>(momentum4Before[Acts::eMom1] /
141  static_cast<float>(momentum4Before[Acts::eMom2] /
143  });
144 
145  to.setEDep(-delta4[Acts::eEnergy] / Acts::UnitConstants::GeV);
146 }
147 
149  const edm4hep::TrackerHitPlane& from,
150  const edm4hep::TrackerHitCollection* fromClusters, Cluster* toCluster,
151  const MapGeometryIdFrom& geometryMapper) {
152  // no need for digitization as we only want to identify the sensor
153  Acts::GeometryIdentifier geometryId = geometryMapper(from.getCellID());
154 
155  IndexSourceLink sourceLink{geometryId, from.id()};
156 
157  auto pos = from.getPosition();
158  auto cov = from.getCovMatrix();
159 
160  DigitizedParameters dParameters;
161 
162  dParameters.indices.push_back(Acts::eBoundLoc0);
163  dParameters.values.push_back(pos.x);
164  dParameters.variances.push_back(cov[0]);
165 
166  // TODO cut this out for 1D
167  dParameters.indices.push_back(Acts::eBoundLoc1);
168  dParameters.values.push_back(pos.y);
169  dParameters.variances.push_back(cov[2]);
170 
171  dParameters.indices.push_back(Acts::eBoundTime);
172  dParameters.values.push_back(pos.z);
173  dParameters.variances.push_back(cov[5]);
174 
175  auto to = createMeasurement(dParameters, sourceLink);
176 
177  if (fromClusters != nullptr) {
178  for (const auto objectId : from.getRawHits()) {
179  const auto& c = fromClusters->at(objectId.index);
180 
181  // TODO get EDM4hep fixed
182  // misusing some fields to store ACTS specific information
183  // don't ask ...
185  static_cast<unsigned int>(c.getType()),
186  static_cast<unsigned int>(c.getQuality())};
188  double activation = c.getTime();
189  ActsFatras::Channelizer::ChannelSegment cell{bin, path2D, activation};
190 
191  toCluster->channels.push_back(cell);
192  }
193  }
194 
195  return to;
196 }
197 
199  edm4hep::MutableTrackerHitPlane to,
200  const Cluster* fromCluster,
201  edm4hep::TrackerHitCollection& toClusters,
202  const MapGeometryIdTo& geometryMapper) {
203  std::visit(
204  [&](const auto& m) {
206  m.sourceLink().template get<IndexSourceLink>().geometryId();
207 
208  if (geometryMapper) {
209  // no need for digitization as we only want to identify the sensor
210  to.setCellID(geometryMapper(geoId));
211  }
212 
213  auto parameters = (m.expander() * m.parameters()).eval();
214 
216 
218  // TODO set uv (which are in global spherical coordinates with r=1)
219  to.setPosition({parameters[Acts::eBoundLoc0],
221  parameters[Acts::eBoundTime]});
222 
223  auto covariance =
224  (m.expander() * m.covariance() * m.expander().transpose()).eval();
225  to.setCovMatrix({
226  static_cast<float>(covariance(Acts::eBoundLoc0, Acts::eBoundLoc0)),
227  static_cast<float>(covariance(Acts::eBoundLoc1, Acts::eBoundLoc0)),
228  static_cast<float>(covariance(Acts::eBoundLoc1, Acts::eBoundLoc1)),
229  0,
230  0,
231  0,
232  });
233 
234  if (fromCluster) {
235  for (const auto& c : fromCluster->channels) {
236  auto toChannel = toClusters.create();
237  to.addToRawHits(toChannel.getObjectID());
238 
239  // TODO digitization channel
240 
241  // TODO get EDM4hep fixed
242  // misusing some fields to store ACTS specific information
243  // don't ask ...
244  toChannel.setType(c.bin[0]);
245  toChannel.setQuality(c.bin[1]);
246  toChannel.setTime(c.activation);
247  }
248  }
249  },
250  from);
251 }
252 
254  const Acts::GeometryContext& gctx, double Bz, const Trajectories& from,
255  edm4hep::MutableTrack to, std::size_t fromIndex,
257  const IndexMultimap<ActsFatras::Barcode>& hitParticlesMap) {
258  const auto& multiTrajectory = from.multiTrajectory();
259  auto trajectoryState =
260  Acts::MultiTrajectoryHelpers::trajectoryState(multiTrajectory, fromIndex);
261 
262  std::vector<ParticleHitCount> particleHitCount;
263  identifyContributingParticles(hitParticlesMap, from, fromIndex,
264  particleHitCount);
265  // TODO use particles
266 
267  // TODO write track params
268  // auto trackParameters = from.trackParameters(fromIndex);
269 
271  to.setNdf(trajectoryState.NDF);
272 
273  multiTrajectory.visitBackwards(fromIndex, [&](const auto& state) {
274  // we only fill the track states with non-outlier measurement
275  auto typeFlags = state.typeFlags();
276  if (!typeFlags.test(Acts::TrackStateFlag::MeasurementFlag)) {
277  return true;
278  }
279 
280  edm4hep::TrackState trackState;
281 
282  Acts::BoundTrackParameters parObj{state.referenceSurface().getSharedPtr(),
283  state.parameters(), state.covariance(),
284  particleHypothesis};
285 
286  // Convert to LCIO track parametrization expected by EDM4hep
287  // This will create an ad-hoc perigee surface if the input parameters are
288  // not bound on a perigee surface already
291  parObj);
292 
293  trackState.D0 = converted.values[0];
294  trackState.Z0 = converted.values[1];
295  trackState.phi = converted.values[2];
296  trackState.tanLambda = converted.values[3];
297  trackState.omega = converted.values[4];
298  trackState.time = converted.values[5];
299 
300  // Converted parameters are relative to an ad-hoc perigee surface created at
301  // the hit location
302  auto center = converted.surface->center(gctx);
303  trackState.referencePoint.x = center.x();
304  trackState.referencePoint.y = center.y();
305  trackState.referencePoint.z = center.z();
306 
307  if (converted.covariance) {
308  const auto& c = converted.covariance.value();
309 
310  trackState.covMatrix = {
311  static_cast<float>(c(0, 0)), static_cast<float>(c(1, 0)),
312  static_cast<float>(c(1, 1)), static_cast<float>(c(2, 0)),
313  static_cast<float>(c(2, 1)), static_cast<float>(c(2, 2)),
314  static_cast<float>(c(3, 0)), static_cast<float>(c(3, 1)),
315  static_cast<float>(c(3, 2)), static_cast<float>(c(3, 3)),
316  static_cast<float>(c(4, 0)), static_cast<float>(c(4, 1)),
317  static_cast<float>(c(4, 2)), static_cast<float>(c(4, 3)),
318  static_cast<float>(c(4, 4))};
319  }
320 
321  to.addToTrackStates(trackState);
322 
323  return true;
324  });
325 }
326 
327 } // namespace ActsExamples