Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DetectorAlignment.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DetectorAlignment.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 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 
9 #include "DetectorAlignment.hpp"
10 
40 
41 #include <filesystem>
42 #include <memory>
43 
44 using namespace Acts::UnitLiterals;
45 using namespace ActsExamples;
46 using namespace std::filesystem;
47 
50  auto opt = desc.add_options();
51  opt("reco-with-misalignment-correction", value<bool>()->default_value(false),
52  "Correct for detector misalignment effects.");
53  opt("alignment-geo-config-file", value<std::string>()->default_value(""),
54  "Json file for alignment geometry elements selection");
55 }
56 
58  int argc, char* argv[],
59  const std::shared_ptr<ActsExamples::IBaseDetector>& detector,
60  ActsAlignment::AlignedTransformUpdater alignedTransformUpdater,
61  const AlignedDetElementGetter& alignedDetElementsGetter) {
62  // using boost::program_options::value;
63 
64  // setup and parse options
65  auto desc = Options::makeDefaultOptions();
72  Options::addOutputOptions(desc, OutputFormat::DirectoryOnly);
73  detector->addOptions(desc);
78  addAlignmentOptions(desc);
79 
80  auto vm = Options::parse(desc, argc, argv);
81  if (vm.empty()) {
82  return EXIT_FAILURE;
83  }
84 
86 
87  // Read some standard options
89  auto outputDir = ensureWritableDirectory(vm["output-dir"].as<std::string>());
90  auto rnd = std::make_shared<const ActsExamples::RandomNumbers>(
92 
93  if (vm["fit-directed-navigation"].as<bool>()) {
94  throw std::runtime_error(
95  "Directed navigation not supported anymore in the examples binaries."
96  "Please refer to the RefittingAlgorithm in the python bindings.");
97  }
98 
99  // Setup detector geometry
100  auto geometry = Geometry::build(vm, *detector);
101  auto trackingGeometry = geometry.first;
102  // Add context decorators
103  for (const auto& cdr : geometry.second) {
104  sequencer.addContextDecorator(cdr);
105  }
106  // Setup the magnetic field
108 
109  // Read the sim hits
110  auto simHitReaderCfg = setupSimHitReading(vm, sequencer);
111  // Read the particles
112  auto particleReader = setupParticleReading(vm, sequencer);
113 
114  // Run the sim hits smearing
115  auto digiCfg = setupDigitization(vm, sequencer, rnd, trackingGeometry,
116  simHitReaderCfg.outputSimHits);
117  // Run the particle selection
118  // The pre-selection will select truth particles satisfying provided criteria
119  // from all particles read in by particle reader for further processing. It
120  // has no impact on the truth hits read-in by the cluster reader.
121  TruthSeedSelector::Config particleSelectorCfg =
123  particleSelectorCfg.inputParticles = particleReader.outputParticles;
124  particleSelectorCfg.inputMeasurementParticlesMap =
125  digiCfg.outputMeasurementParticlesMap;
126  particleSelectorCfg.outputParticles = "particles_selected";
127  particleSelectorCfg.nHitsMin = 9;
128  particleSelectorCfg.ptMin = 500._MeV;
129  sequencer.addAlgorithm(
130  std::make_shared<TruthSeedSelector>(particleSelectorCfg, logLevel));
131 
132  // The selected particles
133  const auto& inputParticles = particleSelectorCfg.outputParticles;
134 
135  // Run the particle smearing
136  auto particleSmearingCfg =
137  setupParticleSmearing(vm, sequencer, rnd, inputParticles);
138 
139  // The fitter needs the measurements (proto tracks) and initial
140  // track states (proto states). The elements in both collections
141  // must match and must be created from the same input particles.
142  // Create truth tracks
143  TruthTrackFinder::Config trackFinderCfg;
144  trackFinderCfg.inputParticles = inputParticles;
145  trackFinderCfg.inputMeasurementParticlesMap =
146  digiCfg.outputMeasurementParticlesMap;
147  trackFinderCfg.outputProtoTracks = "prototracks";
148  sequencer.addAlgorithm(
149  std::make_shared<TruthTrackFinder>(trackFinderCfg, logLevel));
150 
151  if (vm["reco-with-misalignment-correction"].as<bool>()) {
152  // setup the alignment (which will update the aligned transforms of the
153  // detector elements)
155  alignment.inputSourceLinks = digiCfg.outputSourceLinks;
156  alignment.inputMeasurements = digiCfg.outputMeasurements;
157  alignment.inputProtoTracks = trackFinderCfg.outputProtoTracks;
158  alignment.inputInitialTrackParameters =
159  particleSmearingCfg.outputTrackParameters;
160  alignment.outputAlignmentParameters = "alignment-parameters";
161  alignment.alignedTransformUpdater = std::move(alignedTransformUpdater);
162  std::string path = vm["alignment-geo-config-file"].as<std::string>();
163  if (not path.empty()) {
164  alignment.alignedDetElements = alignedDetElementsGetter(
165  detector, ActsExamples::readJsonGeometryList(path));
166  }
167 
168  // The criteria to determine if the iteration has converged.
169  alignment.deltaChi2ONdfCutOff = {10, 0.00005};
170  alignment.chi2ONdfCutOff = 0.01;
171  alignment.maxNumIterations = 60;
172  alignment.align = AlignmentAlgorithm::makeAlignmentFunction(
174  sequencer.addAlgorithm(
175  std::make_shared<AlignmentAlgorithm>(alignment, logLevel));
176  }
177 
178  // setup the fitter
180  fitter.inputMeasurements = digiCfg.outputMeasurements;
181  fitter.inputSourceLinks = digiCfg.outputSourceLinks;
182  fitter.inputProtoTracks = trackFinderCfg.outputProtoTracks;
184  particleSmearingCfg.outputTrackParameters;
185  fitter.outputTracks = "tracks";
186  fitter.pickTrack = vm["fit-pick-track"].as<int>();
189  vm["fit-multiple-scattering-correction"].as<bool>(),
190  vm["fit-energy-loss-correction"].as<bool>());
191  sequencer.addAlgorithm(
192  std::make_shared<TrackFittingAlgorithm>(fitter, logLevel));
193 
194  TracksToTrajectories::Config tracksToTrajCfg{};
195  tracksToTrajCfg.inputTracks = fitter.outputTracks;
196  tracksToTrajCfg.outputTrajectories = "trajectories";
197  sequencer.addAlgorithm(
198  (std::make_shared<TracksToTrajectories>(tracksToTrajCfg, logLevel)));
199 
200  // write track states from fitting
201  RootTrajectoryStatesWriter::Config trackStatesWriter;
202  trackStatesWriter.inputTrajectories = tracksToTrajCfg.outputTrajectories;
203  trackStatesWriter.inputParticles = inputParticles;
204  trackStatesWriter.inputSimHits = simHitReaderCfg.outputSimHits;
205  trackStatesWriter.inputMeasurementParticlesMap =
206  digiCfg.outputMeasurementParticlesMap;
207  trackStatesWriter.inputMeasurementSimHitsMap =
208  digiCfg.outputMeasurementSimHitsMap;
209  trackStatesWriter.filePath = outputDir + "/trackstates_fitter.root";
210  sequencer.addWriter(std::make_shared<RootTrajectoryStatesWriter>(
211  trackStatesWriter, logLevel));
212 
213  // write track summary from CKF
214  RootTrajectorySummaryWriter::Config trackSummaryWriter;
215  trackSummaryWriter.inputTrajectories = tracksToTrajCfg.outputTrajectories;
216  trackSummaryWriter.inputParticles = inputParticles;
217  trackSummaryWriter.inputMeasurementParticlesMap =
218  digiCfg.outputMeasurementParticlesMap;
219  trackSummaryWriter.filePath = outputDir + "/tracksummary_fitter.root";
220  sequencer.addWriter(std::make_shared<RootTrajectorySummaryWriter>(
221  trackSummaryWriter, logLevel));
222 
223  // Write CKF performance data
224  // write reconstruction performance data
226  perfFinder.inputProtoTracks = trackFinderCfg.outputProtoTracks;
227  perfFinder.inputParticles = inputParticles;
228  perfFinder.inputMeasurementParticlesMap =
229  digiCfg.outputMeasurementParticlesMap;
230  perfFinder.filePath = outputDir + "/performance_track_finder.root";
231  sequencer.addWriter(
232  std::make_shared<TrackFinderPerformanceWriter>(perfFinder, logLevel));
233 
235  perfFitter.inputTrajectories = tracksToTrajCfg.outputTrajectories;
236  perfFitter.inputParticles = inputParticles;
237  perfFitter.inputMeasurementParticlesMap =
238  digiCfg.outputMeasurementParticlesMap;
239  perfFitter.filePath = outputDir + "/performance_track_fitter.root";
240  sequencer.addWriter(
241  std::make_shared<TrackFitterPerformanceWriter>(perfFitter, logLevel));
242 
243  return sequencer.run();
244 }