LDMX Software
VertexProcessor.cxx
1#include "Tracking/Reco/VertexProcessor.h"
2
3#include <chrono>
4
5#include "Acts/Surfaces/PerigeeSurface.hpp"
6#include "TFile.h"
7#include "TLorentzVector.h"
8#include "Tracking/Event/Track.h"
9#include "Tracking/Sim/TrackingUtils.h"
10
11using namespace framework;
12
13namespace tracking {
14namespace reco {
15
16VertexProcessor::VertexProcessor(const std::string& name,
17 framework::Process& process)
18 : framework::Producer(name, process) {}
19
21 bctx_ = Acts::MagneticFieldContext();
22
23 h_m_ = new TH1F("m", "m", 100, 0., 1.);
24 h_m_truth_filter_ = new TH1F("m_filter", "m", 100, 0., 1.);
25 h_m_truth_ = new TH1F("m_truth", "m_truth", 100, 0., 1.);
26
27 /*
28 * this is unused, should it be? FIXME
29 auto localToGlobalBin_xyz = [](std::array<size_t, 3> bins,
30 std::array<size_t, 3> sizes) {
31 return (bins[0] * (sizes[1] * sizes[2]) + bins[1] * sizes[2] +
32 bins[2]); // xyz - field space
33 // return (bins[1] * (sizes[2] * sizes[0]) + bins[2] * sizes[0] + bins[0]);
34 // //zxy
35 };
36 */
37
38 // Setup a interpolated bfield map
39 sp_interpolated_b_field_ =
40 std::make_shared<InterpolatedMagneticField3>(loadDefaultBField(
41 field_map_, defaultTransformPos, defaultTransformBField));
42
43 ldmx_log(info) << "Check if nullptr::" << sp_interpolated_b_field_.get();
44}
45
47 // TODO:: the bfield map should be taken automatically
48 field_map_ = parameters.get<std::string>("field_map");
49
50 trk_coll_name_ = parameters.get<std::string>("trk_coll_name", "Tracks");
51
52 seeds_coll_name_ =
53 parameters.get<std::string>("seeds_coll_name", "RecoilTruthSeeds");
54
55 input_pass_name_ = parameters.get<std::string>("input_pass_name");
56}
57
59 // TODO:: Move this to an external file
60 // And move all this to a single time per processor not for each event!!
61
62 nevents_++;
63 auto start = std::chrono::high_resolution_clock::now();
64 auto&& stepper = Acts::EigenStepper<>{sp_interpolated_b_field_};
65
66 // Set up propagator with void navigator
67 propagator_ = std::make_shared<VoidPropagator>(stepper);
68
69 // Note: FullBilloirVertexFitter setup commented out — fit() is not called yet
70 // and v46 Config now requires extractParameters/trackLinearizer delegates.
71 // Acts::VertexingOptions vf_options(gctx_, bctx_);
72
73 // Retrieve the track collection
74 const auto& tracks =
75 event.getCollection<ldmx::Track>(trk_coll_name_, input_pass_name_);
76
77 // Retrieve the truth seeds
78 const auto& seeds =
79 event.getCollection<ldmx::Track>(seeds_coll_name_, input_pass_name_);
80
81 if (tracks.size() < 1) return;
82
83 // Transform the EDM ldmx::tracks to the format needed by ACTS
84 std::vector<Acts::BoundTrackParameters> billoir_tracks;
85
86 // TODO:: The perigee surface should be common between all tracks.
87 // So should only be created once in principle.
88 // There should be no perigeeSurface2
89
90 Acts::Vector3 perigee_acts = tracking::sim::utils::ldmx2Acts(
91 Acts::Vector3(tracks.front().getPerigeeX(), tracks.front().getPerigeeY(),
92 tracks.front().getPerigeeZ()));
93 std::shared_ptr<Acts::PerigeeSurface> perigee_surface =
94 Acts::Surface::makeShared<Acts::PerigeeSurface>(perigee_acts);
95
96 for (unsigned int i_track = 0; i_track < tracks.size(); i_track++) {
97 Acts::BoundVector param_vec;
98 param_vec << tracks.at(i_track).getD0(), tracks.at(i_track).getZ0(),
99 tracks.at(i_track).getPhi(), tracks.at(i_track).getTheta(),
100 tracks.at(i_track).getQoP(), tracks.at(i_track).getT();
101
102 Acts::BoundMatrix cov_mat =
103 tracking::sim::utils::unpackCov(tracks.at(i_track).getPerigeeCov());
104 auto part{Acts::ParticleHypothesis(
105 Acts::PdgParticle(tracks.at(i_track).getPdgID()))};
106 billoir_tracks.push_back(Acts::BoundTrackParameters(
107 perigee_surface, param_vec, std::move(cov_mat), part));
108 }
109
110 // Select exactly 2 tracks
111 if (billoir_tracks.size() != 2) {
112 return;
113 }
114
115 if (billoir_tracks.at(0).charge() * billoir_tracks.at(1).charge() > 0) return;
116
117 // Pion mass hypothesis
118 double pion_mass = 139.570 * Acts::UnitConstants::MeV;
119
120 TLorentzVector p1, p2;
121 p1.SetXYZM(billoir_tracks.at(0).momentum()(0),
122 billoir_tracks.at(0).momentum()(1),
123 billoir_tracks.at(0).momentum()(2), pion_mass);
124
125 p2.SetXYZM(billoir_tracks.at(1).momentum()(0),
126 billoir_tracks.at(1).momentum()(1),
127 billoir_tracks.at(1).momentum()(2), pion_mass);
128
129 std::vector<TLorentzVector> pion_seeds;
130
131 if (seeds.size() == 2) {
132 for (int i_seed = 0; i_seed < seeds.size(); i_seed++) {
133 Acts::Vector3 seed_perigee_acts =
134 tracking::sim::utils::ldmx2Acts(Acts::Vector3(
135 seeds.at(i_seed).getPerigeeX(), seeds.at(i_seed).getPerigeeY(),
136 seeds.at(i_seed).getPerigeeZ()));
137 std::shared_ptr<Acts::PerigeeSurface> perigee_surface2 =
138 Acts::Surface::makeShared<Acts::PerigeeSurface>(seed_perigee_acts);
139
140 Acts::BoundVector param_vec;
141 param_vec << seeds.at(i_seed).getD0(), seeds.at(i_seed).getZ0(),
142 seeds.at(i_seed).getPhi(), seeds.at(i_seed).getTheta(),
143 seeds.at(i_seed).getQoP(), seeds.at(i_seed).getT();
144
145 Acts::BoundMatrix cov_mat =
146 tracking::sim::utils::unpackCov(seeds.at(i_seed).getPerigeeCov());
147 int pion_pdg_id = 211; // pi+
148 if (seeds.at(i_seed).getCharge() < 0) pion_pdg_id = -211;
149 // BoundTrackParameters needs the particle hypothesis
150 auto part{Acts::ParticleHypothesis(Acts::PdgParticle(pion_pdg_id))};
151 auto bound_seed_params = Acts::BoundTrackParameters(
152 perigee_surface, param_vec, std::move(cov_mat), part);
153
154 TLorentzVector pion4v;
155 pion4v.SetXYZM(bound_seed_params.momentum()(0),
156 bound_seed_params.momentum()(1),
157 bound_seed_params.momentum()(2), pion_mass);
158
159 pion_seeds.push_back(pion4v);
160 } // loops on seeds
161
162 h_m_truth_->Fill((pion_seeds.at(0) + pion_seeds.at(1)).M());
163 }
164
165 if ((pion_seeds.size() == 2) &&
166 (pion_seeds.at(0) + pion_seeds.at(1)).M() > 0.490 &&
167 (pion_seeds.at(0) + pion_seeds.at(1)).M() < 0.510) {
168 // Check if the tracks have opposite charge
169 h_m_truth_filter_->Fill((p1 + p2).M());
170 }
171
172 h_m_->Fill((p1 + p2).M());
173
174 auto end = std::chrono::high_resolution_clock::now();
175 // long long microseconds =
176 // std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
177 auto diff = end - start;
178 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
179}
180
182 TFile* outfile = new TFile("VertexingResults.root", "RECREATE");
183 outfile->cd();
184
185 h_m_->Write();
186 h_m_truth_->Write();
187 h_m_truth_filter_->Write();
188 outfile->Close();
189 delete outfile;
190
191 ldmx_log(info) << "AVG Time/Event: " << std::fixed << std::setprecision(3)
192 << processing_time_ / nevents_ << " ms";
193}
194
195} // namespace reco
196} // namespace tracking
197
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Implements an event buffer system for storing event data.
Definition Event.h:40
Class which represents the process under execution.
Definition Process.h:34
Base class for a module which produces a data product.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
Implementation of a track object.
Definition Track.h:54
Acts::MagneticFieldContext bctx_
The contexts - TODO: they should move to some global location, I guess.
void onProcessEnd() override
Callback for the EventProcessor to take any necessary action when the processing of events finishes,...
VertexProcessor(const std::string &name, framework::Process &process)
Constructor.
void configure(framework::config::Parameters &parameters) override
Configure the processor using the given user specified parameters.
std::string field_map_
Path to the magnetic field map.
void produce(framework::Event &event) override
Run the processor.
void onProcessStart() override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...
All classes in the ldmx-sw project use this namespace.
The measurement calibrator can be a function or a class/struct able to retrieve the sim hits containe...