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 gctx_ = Acts::GeometryContext();
48 bctx_ = Acts::MagneticFieldContext();
49
50 /*
51 * This is unused now, should it be?
52 auto localToGlobalBin_xyz = [](std::array<size_t, 3> bins,
53 std::array<size_t, 3> sizes) {
54 return (bins[0] * (sizes[1] * sizes[2]) + bins[1] * sizes[2] +
55 bins[2]); // xyz - field space
56 // return (bins[1] * (sizes[2] * sizes[0]) + bins[2] * sizes[0] + bins[0]);
57 // //zxy
58 };
59 */
60
61 sp_interpolated_bField_ =
62 std::make_shared<InterpolatedMagneticField3>(loadDefaultBField(
63 field_map_, default_transformPos, default_transformBField));
64
65 // There is a sign issue between the vertexing and the perigee representation
66 Acts::Vector3 b_field(0., 0., -1.5 * Acts::UnitConstants::T);
67 bField_ = std::make_shared<Acts::ConstantBField>(b_field);
68
69 std::cout << "Check if nullptr::" << sp_interpolated_bField_.get()
70 << std::endl;
71
72 // Set up propagator with void navigator
73 // auto&& stepper = Acts::EigenStepper<>{sp_interpolated_bField_};
74 // propagator_ = std::make_shared<VoidPropagator>(stepper);
75
76 auto&& stepper_const = Acts::EigenStepper<>{bField_};
77 propagator_ = std::make_shared<VoidPropagator>(stepper_const);
78}
79
80void Vertexer::configure(framework::config::Parameters& parameters) {
81 // TODO:: the bfield map should be taken automatically
82 field_map_ = parameters.getParameter<std::string>("field_map");
83
84 trk_c_name_1 =
85 parameters.getParameter<std::string>("trk_c_name_1", "TaggerTracks");
86 trk_c_name_2 =
87 parameters.getParameter<std::string>("trk_c_name_2", "RecoilTracks");
88}
89
90void Vertexer::produce(framework::Event& event) {
91 nevents_++;
92 // auto start = std::chrono::high_resolution_clock::now();
93
94 // Track linearizer in the proximity of the vertex location
95 using Linearizer = Acts::HelicalTrackLinearizer;
96 Linearizer::Config linearizerConfig;
97 linearizerConfig.bField = bField_;
98 linearizerConfig.propagator = propagator_;
99 Linearizer linearizer(linearizerConfig);
100
101 // Set up Billoir Vertex Fitter
102 using VertexFitter = Acts::FullBilloirVertexFitter;
103
104 // Alternatively one can use
105 // using VertexFitter =
106 // Acts::FullBilloirVertexFitter<tracking::sim::utils::boundTrackParameters,Linearizer>;
107
108 VertexFitter::Config vertexFitterCfg;
109 VertexFitter billoirFitter(vertexFitterCfg);
110 // mg Aug 2024 .. State doesn't exist in v36 and isn't used here anyway
111 // VertexFitter::State state(sp_interpolated_bField_->makeCache(bctx_));
112
113 // Unconstrained fit
114 // See
115 // https://github.com/acts-project/acts/blob/main/Tests/UnitTests/Core/Vertexing/FullBilloirVertexFitterTests.cpp#L149
116 // For constraint implementation
117
118 // Acts::VertexingOptions<Acts::BoundTrackParameters> vfOptions(gctx_,
119 // bctx_);
120 // mg Aug 2024 ... VertexingOptions template change in v36
121 Acts::VertexingOptions vfOptions(gctx_, bctx_);
122
123 // Retrive the two track collections
124
125 const std::vector<ldmx::Track> tracks_1 =
126 event.getCollection<ldmx::Track>(trk_c_name_1);
127 const std::vector<ldmx::Track> tracks_2 =
128 event.getCollection<ldmx::Track>(trk_c_name_2);
129
130 ldmx_log(debug) << "Retrieved track collections" << std::endl
131 << "Track 1 size:" << tracks_1.size() << std::endl
132 << "Track 2 size:" << tracks_2.size() << std::endl;
133
134 if (tracks_1.size() < 1 || tracks_2.size() < 1) return;
135
136 std::vector<Acts::BoundTrackParameters> billoir_tracks_1, billoir_tracks_2;
137
138 // TODO:: The perigee surface should be common between all tracks.
139
140 std::shared_ptr<Acts::PerigeeSurface> perigeeSurface =
141 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
142 tracks_1.front().getPerigeeX(), tracks_1.front().getPerigeeY(),
143 tracks_1.front().getPerigeeZ()));
144
145 // Monitoring of tagger and recoil tracks
146 TaggerRecoilMonitoring(tracks_1, tracks_2);
147
148 // Start the vertex formation
149 // Form a vertex for each combination of tracks found in the same event
150 // between the two track collections
151
152 for (auto& trk : tracks_1) {
153 billoir_tracks_1.push_back(
154 tracking::sim::utils::boundTrackParameters(trk, perigeeSurface));
155 }
156
157 for (auto& trk : tracks_2) {
158 billoir_tracks_2.push_back(
159 tracking::sim::utils::boundTrackParameters(trk, perigeeSurface));
160 }
161
162 // std::vector<Acts::Vertex<Acts::BoundTrackParameters> > fit_vertices;
163 std::vector<Acts::Vertex> fit_vertices;
164
165 for (auto& b_trk_1 : billoir_tracks_1) {
166 std::vector<const Acts::BoundTrackParameters*> fit_tracks_ptr;
167
168 for (auto& b_trk_2 : billoir_tracks_2) {
169 fit_tracks_ptr.push_back(&b_trk_1);
170 fit_tracks_ptr.push_back(&b_trk_2);
171
172 ldmx_log(debug) << "Calling vertex fitter" << std::endl
173 << "Track 1 parameters" << std::endl
174 << b_trk_1 << std::endl
175 << "Track 2 parameters" << std::endl
176 << b_trk_2 << std::endl;
177
178 // std::cout << "Perigee Surface" << std::endl;
179 // perigeeSurface->toStream(gctx_, std::cout);
180 // std::cout << std::endl;
181
182 } // loop on second set of tracks
183
184 nreconstructable_++;
185 try {
186 // Acts::Vertex<Acts::BoundTrackParameters> fitVtx =
187 // billoirFitter.fit(fit_tracks_ptr, linearizer, vfOptions,
188 // state).value(); fit_vertices.push_back(fitVtx);
189 nvertices_++;
190
191 } catch (...) {
192 ldmx_log(warn) << "Vertex fit failed" << std::endl;
193 }
194
195 } // loop on first set
196
197 // Convert the vertices in the ldmx EDM and store them
198}
199
200void Vertexer::onProcessEnd() {
201 ldmx_log(info) << "Reconstructed " << nvertices_ << " vertices over "
202 << nreconstructable_ << " reconstructable" << std::endl;
203
204 TFile* outfile_ = new TFile((getName() + ".root").c_str(), "RECREATE");
205 outfile_->cd();
206
207 h_delta_d0->Write();
208 h_delta_z0->Write();
209 h_delta_p->Write();
210 h_delta_phi->Write();
211 h_delta_theta->Write();
212
213 h_delta_d0_vs_recoil_p->Write();
214 h_delta_z0_vs_recoil_p->Write();
215
216 h_td0_vs_rd0->Write();
217 h_tz0_vs_rz0->Write();
218
219 outfile_->Close();
220 delete outfile_;
221}
222
223void Vertexer::TaggerRecoilMonitoring(
224 const std::vector<ldmx::Track>& tagger_tracks,
225 const std::vector<ldmx::Track>& recoil_tracks) {
226 // For the moment only check that I have 1 tagger track and one recoil track
227 // To avoid trying to match them
228 // TODO update this logic
229
230 if (tagger_tracks.size() != 1 || recoil_tracks.size() != 1) return;
231
232 ldmx::Track t_trk = tagger_tracks.at(0);
233 ldmx::Track r_trk = recoil_tracks.at(0);
234
235 double t_p, r_p;
236 // these are unsed, should they be? FIXME
237 // double t_d0, r_d0;
238 // double tt_p_phi, r_phi;
239 // double t_theta, r_theta;
240 // double t_z0, r_z0;
241
242 t_p = t_trk.q() / t_trk.getQoP();
243 r_p = r_trk.q() / r_trk.getQoP();
244
245 h_delta_d0->Fill(t_trk.getD0() - r_trk.getD0());
246 h_delta_z0->Fill(t_trk.getZ0() - r_trk.getZ0());
247 h_delta_p->Fill(t_p - r_p);
248 h_delta_phi->Fill(t_trk.getPhi() - r_trk.getPhi());
249 h_delta_theta->Fill(t_trk.getTheta() - r_trk.getTheta());
250
251 // differential plots
252
253 h_delta_d0_vs_recoil_p->Fill(r_p, t_trk.getD0() - r_trk.getD0());
254 h_delta_z0_vs_recoil_p->Fill(r_p, t_trk.getZ0() - r_trk.getZ0());
255
256 //"beamspot"
257 h_td0_vs_rd0->Fill(r_trk.getD0(), t_trk.getD0());
258 h_tz0_vs_rz0->Fill(r_trk.getZ0(), t_trk.getZ0());
259
260 //"pT"
261 // TODO Transverse momentum should obtained orthogonal to the B-Field
262 // direction This assumes to be along Z (which is not very accurate)
263
264 // std::vector<double> r_mom = r_trk.getMomentum();
265 // std::vector<double> t_mom = t_trk.getMomentum();
266
267 // I assume to have a single photon being emitted in the target: I use
268 // momentum conservation p_photon = p_beam - p_recoil
269
270 // h_gamma_px->Fill(t_mom[0] - r_mom[0]);
271 // h_gamma_py->Fill(t_mom[1] - r_mom[1]);
272 // h_gamma_pz->Fill(t_mom[2] - r_mom[2]);
273}
274
275} // namespace reco
276} // namespace tracking
277
278DECLARE_PRODUCER_NS(tracking::reco, Vertexer)
#define DECLARE_PRODUCER_NS(NS, 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:41
Class which represents the process under execution.
Definition Process.h:36
Base class for a module which produces a data product.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:27
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
Implementation of a track object.
Definition Track.h:52
All classes in the ldmx-sw project use this namespace.
Definition PerfDict.cxx:45
The measurement calibrator can be a function or a class/struct able to retrieve the sim hits containe...