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