Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RecCKFTracks.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RecCKFTracks.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019-2021 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 
11 #ifdef ACTS_PLUGIN_ONNX
13 #endif
44 
45 #include <filesystem>
46 #include <memory>
47 
48 using namespace Acts::UnitLiterals;
49 using namespace ActsExamples;
50 using namespace std::filesystem;
51 using namespace std::placeholders;
52 
54  using namespace ActsExamples;
55  using boost::program_options::bool_switch;
56 
57  auto opt = desc.add_options();
58  opt("ckf-truth-smeared-seeds", bool_switch(),
59  "Use track parameters smeared from truth particles for steering CKF");
60  opt("ckf-truth-estimated-seeds", bool_switch(),
61  "Use track parameters estimated from truth tracks for steering CKF");
62 }
63 
65  int argc, char* argv[],
66  const std::shared_ptr<ActsExamples::IBaseDetector>& detector) {
67  // setup and parse options
75  OutputFormat::Csv | OutputFormat::DirectoryOnly);
76  detector->addOptions(desc);
80  addRecCKFOptions(desc);
85 
86  auto vm = Options::parse(desc, argc, argv);
87  if (vm.empty()) {
88  return EXIT_FAILURE;
89  }
90 
92 
93  // Read some standard options
95  auto inputDir = vm["input-dir"].as<std::string>();
96  auto outputDir = ensureWritableDirectory(vm["output-dir"].as<std::string>());
97  auto rnd = std::make_shared<ActsExamples::RandomNumbers>(
99  bool truthSmearedSeeded = vm["ckf-truth-smeared-seeds"].template as<bool>();
100  bool truthEstimatedSeeded =
101  vm["ckf-truth-estimated-seeds"].template as<bool>();
102 
103  // Setup detector geometry
104  auto geometry = Geometry::build(vm, *detector);
105  auto trackingGeometry = geometry.first;
106  // Add context decorators
107  for (const auto& cdr : geometry.second) {
108  sequencer.addContextDecorator(cdr);
109  }
110  // Set up the magnetic field
112 
113  // Read the sim hits
114  auto simHitReaderCfg = setupSimHitReading(vm, sequencer);
115  // Read the particles
116  auto particleReader = setupParticleReading(vm, sequencer);
117 
118  // Run the sim hits smearing
119  auto digiCfg = setupDigitization(vm, sequencer, rnd, trackingGeometry,
120  simHitReaderCfg.outputSimHits);
121 
122  // Run the particle selection
123  // The pre-selection will select truth particles satisfying provided criteria
124  // from all particles read in by particle reader for further processing. It
125  // has no impact on the truth hits read-in by the cluster reader.
126  TruthSeedSelector::Config particleSelectorCfg;
127  particleSelectorCfg.inputParticles = particleReader.outputParticles;
128  particleSelectorCfg.inputMeasurementParticlesMap =
129  digiCfg.outputMeasurementParticlesMap;
130  particleSelectorCfg.outputParticles = "particles_selected";
131  particleSelectorCfg.ptMin = 500_MeV;
132  particleSelectorCfg.nHitsMin = 9;
133  sequencer.addAlgorithm(
134  std::make_shared<TruthSeedSelector>(particleSelectorCfg, logLevel));
135 
136  // The selected particles
137  const auto& inputParticles = particleSelectorCfg.outputParticles;
138 
139  // Create starting parameters from either particle smearing or combined seed
140  // finding and track parameters estimation
141  std::string outputTrackParameters;
142  if (truthSmearedSeeded) {
143  // Run the particle smearing
144  auto particleSmearingCfg =
145  setupParticleSmearing(vm, sequencer, rnd, inputParticles);
146  outputTrackParameters = particleSmearingCfg.outputTrackParameters;
147  } else {
148  // Create space points
150  spCfg.inputSourceLinks = digiCfg.outputSourceLinks;
151  spCfg.inputMeasurements = digiCfg.outputMeasurements;
152  spCfg.outputSpacePoints = "spacepoints";
154  sequencer.addAlgorithm(std::make_shared<SpacePointMaker>(spCfg, logLevel));
155 
156  // Create seeds (i.e. proto tracks) using either truth track finding or seed
157  // finding algorithm
158  std::string inputProtoTracks = "";
159  std::string inputSeeds = "";
160  if (truthEstimatedSeeded) {
161  // Truth track finding algorithm
162  TruthTrackFinder::Config trackFinderCfg;
163  trackFinderCfg.inputParticles = inputParticles;
164  trackFinderCfg.inputMeasurementParticlesMap =
165  digiCfg.outputMeasurementParticlesMap;
166  trackFinderCfg.outputProtoTracks = "prototracks";
167  sequencer.addAlgorithm(
168  std::make_shared<TruthTrackFinder>(trackFinderCfg, logLevel));
169  inputProtoTracks = trackFinderCfg.outputProtoTracks;
170  } else {
171  // Seeding algorithm
172  SeedingAlgorithm::Config seedingCfg;
173  seedingCfg.inputSpacePoints = {
174  spCfg.outputSpacePoints,
175  };
176  seedingCfg.outputSeeds = "seeds";
177 
178  seedingCfg.gridConfig.rMax = 200._mm;
179  seedingCfg.seedFinderConfig.rMax = seedingCfg.gridConfig.rMax;
180 
181  seedingCfg.seedFilterConfig.deltaRMin = 1_mm;
182  seedingCfg.seedFinderConfig.deltaRMin =
183  seedingCfg.seedFilterConfig.deltaRMin;
184 
185  seedingCfg.gridConfig.deltaRMax = 60._mm;
186  seedingCfg.seedFinderConfig.deltaRMax = seedingCfg.gridConfig.deltaRMax;
187 
188  seedingCfg.seedFinderConfig.collisionRegionMin = -250_mm;
189  seedingCfg.seedFinderConfig.collisionRegionMax = 250._mm;
190 
191  seedingCfg.gridConfig.zMin = -2000._mm;
192  seedingCfg.gridConfig.zMax = 2000._mm;
193  seedingCfg.seedFinderConfig.zMin = seedingCfg.gridConfig.zMin;
194  seedingCfg.seedFinderConfig.zMax = seedingCfg.gridConfig.zMax;
195 
196  seedingCfg.seedFilterConfig.maxSeedsPerSpM = 1;
197  seedingCfg.seedFinderConfig.maxSeedsPerSpM =
198  seedingCfg.seedFilterConfig.maxSeedsPerSpM;
199 
200  seedingCfg.gridConfig.cotThetaMax = 7.40627; // 2.7 eta
201  seedingCfg.seedFinderConfig.cotThetaMax =
202  seedingCfg.gridConfig.cotThetaMax;
203 
204  seedingCfg.seedFinderConfig.sigmaScattering = 50;
205  seedingCfg.seedFinderConfig.radLengthPerSeed = 0.1;
206 
207  seedingCfg.gridConfig.minPt = 500._MeV;
208  seedingCfg.seedFinderConfig.minPt = seedingCfg.gridConfig.minPt;
209 
210  seedingCfg.gridOptions.bFieldInZ = 1.99724_T;
211 
212  seedingCfg.seedFinderOptions.bFieldInZ = seedingCfg.gridOptions.bFieldInZ;
213  seedingCfg.seedFinderOptions.beamPos = {0_mm, 0_mm};
214 
215  seedingCfg.seedFinderConfig.impactMax = 3._mm;
216 
217  sequencer.addAlgorithm(
218  std::make_shared<SeedingAlgorithm>(seedingCfg, logLevel));
219 
220  SeedsToPrototracks::Config seedsToPrototrackCfg;
221  seedsToPrototrackCfg.inputSeeds = seedingCfg.outputSeeds;
222  seedsToPrototrackCfg.outputProtoTracks = "prototracks";
223  sequencer.addAlgorithm(
224  std::make_shared<SeedsToPrototracks>(seedsToPrototrackCfg, logLevel));
225 
226  inputProtoTracks = seedsToPrototrackCfg.outputProtoTracks;
227  inputSeeds = seedingCfg.outputSeeds;
228  }
229 
230  // write track finding/seeding performance
232  tfPerfCfg.inputProtoTracks = inputProtoTracks;
233  // using selected particles
234  tfPerfCfg.inputParticles = inputParticles;
235  tfPerfCfg.inputMeasurementParticlesMap =
236  digiCfg.outputMeasurementParticlesMap;
237  tfPerfCfg.filePath = outputDir + "/performance_seeding_trees.root";
238  sequencer.addWriter(
239  std::make_shared<TrackFinderPerformanceWriter>(tfPerfCfg, logLevel));
240 
241  // Algorithm estimating track parameter from seed
242  TrackParamsEstimationAlgorithm::Config paramsEstimationCfg;
243  paramsEstimationCfg.inputSeeds = inputSeeds;
244  paramsEstimationCfg.outputTrackParameters = "estimatedparameters";
245  paramsEstimationCfg.trackingGeometry = trackingGeometry;
246  paramsEstimationCfg.magneticField = magneticField;
247  paramsEstimationCfg.bFieldMin = 0.1_T;
248  paramsEstimationCfg.initialSigmas = {25._um, 100._um, 0.02_degree,
249  0.02_degree, 0.1 / 1._GeV, 1400._s};
250  paramsEstimationCfg.initialVarInflation =
251  vm["ckf-initial-variance-inflation"].template as<Options::Reals<6>>();
252 
253  sequencer.addAlgorithm(std::make_shared<TrackParamsEstimationAlgorithm>(
254  paramsEstimationCfg, logLevel));
255 
256  outputTrackParameters = paramsEstimationCfg.outputTrackParameters;
257  }
258 
259  // Set up the track finding algorithm with CKF
260  // It takes all the source links created from truth hit smearing, seeds from
261  // truth particle smearing and source link selection config
262  auto trackFindingCfg = Options::readTrackFindingConfig(vm);
263  trackFindingCfg.inputMeasurements = digiCfg.outputMeasurements;
264  trackFindingCfg.inputSourceLinks = digiCfg.outputSourceLinks;
265  trackFindingCfg.inputInitialTrackParameters = outputTrackParameters;
266  trackFindingCfg.outputTracks = "tracks";
267  trackFindingCfg.computeSharedHits = true;
268  trackFindingCfg.findTracks = TrackFindingAlgorithm::makeTrackFinderFunction(
270  *Acts::getDefaultLogger("TrackFinder", logLevel));
271  sequencer.addAlgorithm(
272  std::make_shared<TrackFindingAlgorithm>(trackFindingCfg, logLevel));
273 
274  TracksToTrajectories::Config tracksToTrajCfg{};
275  tracksToTrajCfg.inputTracks = trackFindingCfg.outputTracks;
276  tracksToTrajCfg.outputTrajectories = "trajectories";
277  sequencer.addAlgorithm(
278  (std::make_shared<TracksToTrajectories>(tracksToTrajCfg, logLevel)));
279 
280  // write track states from CKF
281  RootTrajectoryStatesWriter::Config trackStatesWriter;
282  trackStatesWriter.inputTrajectories = tracksToTrajCfg.outputTrajectories;
283  // @note The full particles collection is used here to avoid lots of warnings
284  // since the unselected CKF track might have a majority particle not in the
285  // filtered particle collection. This could be avoided when a separate track
286  // selection algorithm is used.
287  trackStatesWriter.inputParticles = particleReader.outputParticles;
288  trackStatesWriter.inputSimHits = simHitReaderCfg.outputSimHits;
289  trackStatesWriter.inputMeasurementParticlesMap =
290  digiCfg.outputMeasurementParticlesMap;
291  trackStatesWriter.inputMeasurementSimHitsMap =
292  digiCfg.outputMeasurementSimHitsMap;
293  trackStatesWriter.filePath = outputDir + "/trackstates_ckf.root";
294  trackStatesWriter.treeName = "trackstates";
295  sequencer.addWriter(std::make_shared<RootTrajectoryStatesWriter>(
296  trackStatesWriter, logLevel));
297 
298  // write track summary from CKF
299  RootTrajectorySummaryWriter::Config trackSummaryWriter;
300  trackSummaryWriter.inputTrajectories = tracksToTrajCfg.outputTrajectories;
301  // @note The full particles collection is used here to avoid lots of warnings
302  // since the unselected CKF track might have a majority particle not in the
303  // filtered particle collection. This could be avoided when a separate track
304  // selection algorithm is used.
305  trackSummaryWriter.inputParticles = particleReader.outputParticles;
306  trackSummaryWriter.inputMeasurementParticlesMap =
307  digiCfg.outputMeasurementParticlesMap;
308  trackSummaryWriter.filePath = outputDir + "/tracksummary_ckf.root";
309  trackSummaryWriter.treeName = "tracksummary";
310  sequencer.addWriter(std::make_shared<RootTrajectorySummaryWriter>(
311  trackSummaryWriter, logLevel));
312 
313  // Write CKF performance data
314  CKFPerformanceWriter::Config perfWriterCfg;
315  perfWriterCfg.inputParticles = inputParticles;
316  perfWriterCfg.inputTrajectories = tracksToTrajCfg.outputTrajectories;
317  perfWriterCfg.inputMeasurementParticlesMap =
318  digiCfg.outputMeasurementParticlesMap;
319  perfWriterCfg.filePath = outputDir + "/performance_ckf.root";
320 #ifdef ACTS_PLUGIN_ONNX
321  // Onnx plugin related options
322  // Path to default demo ML model for track classification
323  path currentFilePath(__FILE__);
324  path parentPath = currentFilePath.parent_path();
325  path demoModelPath =
326  canonical(parentPath / "MLAmbiguityResolutionDemo.onnx").native();
327  // Threshold probability for neural network to classify track as duplicate
328  double decisionThreshProb = 0.5;
329  // Initialize OnnxRuntime plugin
330  Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "MLTrackClassifier");
331  Acts::MLTrackClassifier neuralNetworkClassifier(env, demoModelPath.c_str());
332  perfWriterCfg.duplicatedPredictor =
333  std::bind(&Acts::MLTrackClassifier::isDuplicate, &neuralNetworkClassifier,
334  std::placeholders::_1, decisionThreshProb);
335 #endif
336  sequencer.addWriter(
337  std::make_shared<CKFPerformanceWriter>(perfWriterCfg, logLevel));
338 
339  if (vm["output-csv"].template as<bool>()) {
340  // Write the CKF track as Csv
341  CsvMultiTrajectoryWriter::Config trackWriterCsvConfig;
342  trackWriterCsvConfig.inputTrajectories = tracksToTrajCfg.outputTrajectories;
343  trackWriterCsvConfig.outputDir = outputDir;
344  trackWriterCsvConfig.inputMeasurementParticlesMap =
345  digiCfg.outputMeasurementParticlesMap;
346  sequencer.addWriter(std::make_shared<CsvMultiTrajectoryWriter>(
347  trackWriterCsvConfig, logLevel));
348  }
349 
350  return sequencer.run();
351 }