LDMX Software
Vertexer.cxx
1#include "Tracking/Reco/Vertexer.h"
2
3#include "Acts/Definitions/Units.hpp"
4#include "Acts/Surfaces/PerigeeSurface.hpp"
5#include "Acts/Vertexing/Vertex.hpp"
6#include "TFile.h"
7#include "Tracking/Sim/TrackingUtils.h"
8using namespace framework;
9
10// This producer takes in input two track collections and forms all possible
11// vertices from those It can be used to match the tagger and recoil tracks at
12// the target and form the beamspot
13
14// TODO Move all the performance monitor to another processor
15
16namespace tracking {
17namespace reco {
18
19Vertexer::Vertexer(const std::string& name, framework::Process& process)
20 : framework::Producer(name, process) {}
21
22void Vertexer::onProcessStart() {
23 // Monitoring plots
24
25 double d0min = -2;
26 double d0max = 2;
27 double z0min = -2;
28 double z0max = 2;
29
30 h_delta_d0_ = new TH1F("h_delta_d0", "h_delta_d0", 400, d0min, d0max);
31 h_delta_z0_ = new TH1F("h_delta_z0", "h_delta_z0", 200, z0min, z0max);
32 h_delta_p_ = new TH1F("h_delta_p", "h_delta_p", 200, -1, 4);
33 // h_delta_pT_vsP = new TH2D("h_delta_pT_vs_p","h_delta_pT_v_p",200,)
34 h_delta_phi_ = new TH1F("h_delta_phi", "h_delta_phi", 400, -0.2, 0.2);
35 h_delta_theta_ = new TH1F("h_delta_theta", "h_delta_theta", 200, -0.1, 0.1);
36
37 h_delta_d0_vs_recoil_p_ =
38 new TH2F("h_delta_d0_vs_recoil_p", "h_delta_d0_vs_recoil_p", 200, 0, 5,
39 400, -1, 1);
40 h_delta_z0_vs_recoil_p_ =
41 new TH2F("h_delta_z0_vs_recoil_p", "h_delta_z0_vs_recoil_p", 200, 0, 5,
42 400, -1, 1);
43
44 h_td0_vs_rd0_ =
45 new TH2F("h_td0_vs_rd0", "h_td0_vs_rd0", 100, -40, 40, 100, -40, 40);
46 h_tz0_vs_rz0_ =
47 new TH2F("h_tz0_vs_rz0", "h_tz0_vs_rz0", 100, -40, 40, 100, -40, 40);
48
49 bctx_ = Acts::MagneticFieldContext();
50
51 /*
52 * This is unused now, should it be?
53 auto localToGlobalBin_xyz = [](std::array<size_t, 3> bins,
54 std::array<size_t, 3> sizes) {
55 return (bins[0] * (sizes[1] * sizes[2]) + bins[1] * sizes[2] +
56 bins[2]); // xyz - field space
57 // return (bins[1] * (sizes[2] * sizes[0]) + bins[2] * sizes[0] + bins[0]);
58 // //zxy
59 };
60 */
61
62 sp_interpolated_b_field_ =
63 std::make_shared<InterpolatedMagneticField3>(loadDefaultBField(
64 field_map_, defaultTransformPos, defaultTransformBField));
65
66 // There is a sign issue between the vertexing and the perigee representation
67 Acts::Vector3 b_field(0., 0., -1.5 * Acts::UnitConstants::T);
68 b_field_ = std::make_shared<Acts::ConstantBField>(b_field);
69
70 std::cout << "Check if nullptr::" << sp_interpolated_b_field_.get()
71 << std::endl;
72
73 // Set up propagator with void navigator
74 // auto&& stepper = Acts::EigenStepper<>{sp_interpolated_bField_};
75 // propagator_ = std::make_shared<VoidPropagator>(stepper);
76
77 auto&& stepper_const = Acts::EigenStepper<>{b_field_};
78 propagator_ = std::make_shared<VoidPropagator>(stepper_const);
79}
80
81void Vertexer::configure(framework::config::Parameters& parameters) {
82 // TODO:: the bfield map should be taken automatically
83 field_map_ = parameters.get<std::string>("field_map");
84
85 trk_c_name_1_ = parameters.get<std::string>("trk_c_name_1", "TaggerTracks");
86 trk_c_name_2_ = parameters.get<std::string>("trk_c_name_2", "RecoilTracks");
87 input_pass_name_ = parameters.get<std::string>("input_pass_name");
88}
89
90void Vertexer::produce(framework::Event& event) {
91 nevents_++;
92 // auto start = std::chrono::high_resolution_clock::now();
93
94 // Note: FullBilloirVertexFitter setup commented out — fit() is not called
95 // and v46 Config now requires extractParameters/trackLinearizer delegates.
96 // Acts::VertexingOptions vf_options(gctx_, bctx_);
97
98 // Retrive the two track collections
99
100 const auto& tracks_1 =
101 event.getCollection<ldmx::Track>(trk_c_name_1_, input_pass_name_);
102 const auto& tracks_2 =
103 event.getCollection<ldmx::Track>(trk_c_name_2_, input_pass_name_);
104
105 ldmx_log(debug) << "Retrieved track collections" << std::endl
106 << "Track 1 size:" << tracks_1.size() << std::endl
107 << "Track 2 size:" << tracks_2.size() << std::endl;
108
109 if (tracks_1.size() < 1 || tracks_2.size() < 1) return;
110
111 std::vector<Acts::BoundTrackParameters> billoir_tracks_1, billoir_tracks_2;
112
113 // TODO:: The perigee surface should be common between all tracks.
114
115 Acts::Vector3 perigee_acts = tracking::sim::utils::ldmx2Acts(Acts::Vector3(
116 tracks_1.front().getPerigeeX(), tracks_1.front().getPerigeeY(),
117 tracks_1.front().getPerigeeZ()));
118 std::shared_ptr<Acts::PerigeeSurface> perigee_surface =
119 Acts::Surface::makeShared<Acts::PerigeeSurface>(perigee_acts);
120
121 // Monitoring of tagger and recoil tracks
122 taggerRecoilMonitoring(tracks_1, tracks_2);
123
124 // Start the vertex formation
125 // Form a vertex for each combination of tracks found in the same event
126 // between the two track collections
127
128 for (auto& trk : tracks_1) {
129 billoir_tracks_1.push_back(
130 tracking::sim::utils::boundTrackParameters(trk, perigee_surface));
131 }
132
133 for (auto& trk : tracks_2) {
134 billoir_tracks_2.push_back(
135 tracking::sim::utils::boundTrackParameters(trk, perigee_surface));
136 }
137
138 // std::vector<Acts::Vertex<Acts::BoundTrackParameters> > fit_vertices;
139 std::vector<Acts::Vertex> fit_vertices;
140
141 for (auto& b_trk_1 : billoir_tracks_1) {
142 std::vector<const Acts::BoundTrackParameters*> fit_tracks_ptr;
143
144 for (auto& b_trk_2 : billoir_tracks_2) {
145 fit_tracks_ptr.push_back(&b_trk_1);
146 fit_tracks_ptr.push_back(&b_trk_2);
147
148 ldmx_log(debug) << "Calling vertex fitter" << std::endl
149 << "Track 1 parameters" << std::endl
150 << b_trk_1 << std::endl
151 << "Track 2 parameters" << std::endl
152 << b_trk_2 << std::endl;
153
154 // std::cout << "Perigee Surface" << std::endl;
155 // perigeeSurface->toStream(gctx_, std::cout);
156 // std::cout << std::endl;
157
158 } // loop on second set of tracks
159
160 nreconstructable_++;
161 try {
162 // Acts::Vertex<Acts::BoundTrackParameters> fitVtx =
163 // billoirFitter.fit(fit_tracks_ptr, linearizer, vfOptions,
164 // state).value(); fit_vertices.push_back(fitVtx);
165 nvertices_++;
166
167 } catch (...) {
168 ldmx_log(warn) << "Vertex fit failed" << std::endl;
169 }
170
171 } // loop on first set
172
173 // Convert the vertices in the ldmx EDM and store them
174}
175
176void Vertexer::onProcessEnd() {
177 ldmx_log(info) << "Reconstructed " << nvertices_ << " vertices over "
178 << nreconstructable_ << " reconstructable" << std::endl;
179
180 TFile* outfile = new TFile((getName() + ".root").c_str(), "RECREATE");
181 outfile->cd();
182
183 h_delta_d0_->Write();
184 h_delta_z0_->Write();
185 h_delta_p_->Write();
186 h_delta_phi_->Write();
187 h_delta_theta_->Write();
188
189 h_delta_d0_vs_recoil_p_->Write();
190 h_delta_z0_vs_recoil_p_->Write();
191
192 h_td0_vs_rd0_->Write();
193 h_tz0_vs_rz0_->Write();
194
195 outfile->Close();
196 delete outfile;
197}
198
199void Vertexer::taggerRecoilMonitoring(
200 const std::vector<ldmx::Track>& tagger_tracks,
201 const std::vector<ldmx::Track>& recoil_tracks) {
202 // For the moment only check that I have 1 tagger track and one recoil track
203 // To avoid trying to match them
204 // TODO update this logic
205
206 if (tagger_tracks.size() != 1 || recoil_tracks.size() != 1) return;
207
208 ldmx::Track t_trk = tagger_tracks.at(0);
209 ldmx::Track r_trk = recoil_tracks.at(0);
210
211 double t_p, r_p;
212 // these are unsed, should they be? FIXME
213 // double t_d0, r_d0;
214 // double tt_p_phi, r_phi;
215 // double t_theta, r_theta;
216 // double t_z0, r_z0;
217
218 t_p = t_trk.getCharge() / t_trk.getQoP();
219 r_p = r_trk.getCharge() / r_trk.getQoP();
220
221 h_delta_d0_->Fill(t_trk.getD0() - r_trk.getD0());
222 h_delta_z0_->Fill(t_trk.getZ0() - r_trk.getZ0());
223 h_delta_p_->Fill(t_p - r_p);
224 h_delta_phi_->Fill(t_trk.getPhi() - r_trk.getPhi());
225 h_delta_theta_->Fill(t_trk.getTheta() - r_trk.getTheta());
226
227 // differential plots
228
229 h_delta_d0_vs_recoil_p_->Fill(r_p, t_trk.getD0() - r_trk.getD0());
230 h_delta_z0_vs_recoil_p_->Fill(r_p, t_trk.getZ0() - r_trk.getZ0());
231
232 //"beamspot"
233 h_td0_vs_rd0_->Fill(r_trk.getD0(), t_trk.getD0());
234 h_tz0_vs_rz0_->Fill(r_trk.getZ0(), t_trk.getZ0());
235
236 //"pT"
237 // TODO Transverse momentum should obtained orthogonal to the B-Field
238 // direction This assumes to be along Z (which is not very accurate)
239
240 // std::vector<double> r_mom = r_trk.getMomentum();
241 // std::vector<double> t_mom = t_trk.getMomentum();
242
243 // I assume to have a single photon being emitted in the target: I use
244 // momentum conservation p_photon = p_beam - p_recoil
245
246 // h_gamma_px->Fill(t_mom[0] - r_mom[0]);
247 // h_gamma_py->Fill(t_mom[1] - r_mom[1]);
248 // h_gamma_pz->Fill(t_mom[2] - r_mom[2]);
249}
250
251} // namespace reco
252} // namespace tracking
253
#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
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...