LDMX Software
SeedFinderProcessor.cxx
1#include "Tracking/Reco/SeedFinderProcessor.h"
2
3#include "Acts/Definitions/TrackParametrization.hpp"
4#include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp"
5#include "Eigen/Dense"
6#include "Tracking/Sim/TrackingUtils.h"
7
8/* This processor takes in input a set of 3D space points and builds seedTracks
9 * using the ACTS algorithm which is based on the ATLAS 3-space point conformal
10 * fit.
11 *
12 */
13
14using Eigen::MatrixXd;
15using Eigen::VectorXd;
16
17namespace tracking {
18namespace reco {
19
21 framework::Process& process)
22 : TrackingGeometryUser(name, process) {
23 // TODO REMOVE FROM DEFAULT
24 /*
25 output_file_ = new TFile("seeder.root", "RECREATE");
26 output_tree_ = new TTree("seeder", "seeder");
27
28 output_tree_->Branch("nevents", &nevents_);
29 output_tree_->Branch("xhit", &xhit_);
30 output_tree_->Branch("yhit", &yhit_);
31 output_tree_->Branch("zhit", &zhit_);
32
33 output_tree_->Branch("b0", &b0_);
34 output_tree_->Branch("b1", &b1_);
35 output_tree_->Branch("b2", &b2_);
36 output_tree_->Branch("b3", &b3_);
37 output_tree_->Branch("b4", &b4_);
38 */
39}
40
42 truth_matching_tool_ = std::make_shared<tracking::sim::TruthMatchingTool>();
43}
44
46 // Output seed name
47 out_seed_collection_ = parameters.get<std::string>("out_seed_collection",
48 getName() + "SeedTracks");
49
50 // Input strip hits
52 parameters.get<std::string>("input_hits_collection", "TaggerSimHits");
53
54 // Tagger tracks - only for Recoil Seed finding
56 parameters.get<std::string>("tagger_trks_collection", "TaggerTracks");
57
59 parameters.get<std::vector<double>>("perigee_location", {-700, 0., 0.});
60 pmin_ = parameters.get<double>("pmin", 0.05 * Acts::UnitConstants::GeV);
61 pmax_ = parameters.get<double>("pmax", 8 * Acts::UnitConstants::GeV);
62 d0max_ = parameters.get<double>("d0max", -15. * Acts::UnitConstants::mm);
63 d0min_ = parameters.get<double>("d0min", -45. * Acts::UnitConstants::mm);
64 z0max_ = parameters.get<double>("z0max", 60. * Acts::UnitConstants::mm);
65 phicut_ = parameters.get<double>("phicut", 0.1);
66 thetacut_ = parameters.get<double>("thetacut", 0.2);
67 loc0cut_ = parameters.get<double>("loc0cut", 0.1);
68 loc1cut_ = parameters.get<double>("loc1cut", 0.3);
70 parameters.get<std::vector<std::string>>("strategies", {"0,1,2,3,4"});
71 inflate_factors_ = parameters.get<std::vector<double>>(
72 "inflate_factors", {10., 10., 10., 10., 10., 10.});
73 bfield_ = parameters.get<double>("bfield", 1.5);
74 input_pass_name_ = parameters.get<std::string>("input_pass_name");
75 sim_particles_coll_name_ =
76 parameters.get<std::string>("sim_particles_coll_name");
77 sim_particles_passname_ =
78 parameters.get<std::string>("sim_particles_passname");
79 tagger_trks_event_collection_passname_ =
80 parameters.get<std::string>("tagger_trks_event_collection_passname");
81 sim_particles_event_passname_ =
82 parameters.get<std::string>("sim_particles_event_passname");
83 u_error_ = parameters.get<double>("u_error");
84 v_error_ = parameters.get<double>("v_error");
85}
86
88 // tg is unused, should it be? FIXME
89 // const auto& tg{geometry()};
90 auto start = std::chrono::high_resolution_clock::now();
91 std::vector<ldmx::Track> seed_tracks;
92
93 nevents_++;
94
95 // check if SimParticleMap is available for truth matching
96 std::map<int, ldmx::SimParticle> particle_map;
97
98 const auto& measurements = event.getCollection<ldmx::Measurement>(
99 input_hits_collection_, input_pass_name_);
100
101 std::vector<ldmx::Track> tagger_tracks;
103 tagger_trks_event_collection_passname_)) {
104 tagger_tracks = event.getCollection<ldmx::Track>(tagger_trks_collection_,
105 input_pass_name_);
106 }
107
108 // Create an unbound surface at the target
109 std::shared_ptr<Acts::Surface> tgt_surf =
110 tracking::sim::utils::unboundSurface(0.);
111
112 // Create the pseudomeasurements at the target
113
114 ldmx::Measurements target_pseudo_meas;
115
116 for (auto tagtrk : tagger_tracks) {
117 // For Track, the perigee parameters are stored at the target surface.
118 // Use d0/z0 as local position and the perigee covariance for the
119 // pseudo measurement. Only create the pseudo measurement if cov is
120 // available.
121
122 // The covariance matrix passed to the pseudo measurement is considered as
123 // uncorrelated. This is an approx that considers that loc-u and loc-v from
124 // the track have small correlation.
125
126 const auto& perigee_cov = tagtrk.getPerigeeCov();
127 if (!perigee_cov.empty()) {
128 Acts::BoundMatrix cov = tracking::sim::utils::unpackCov(perigee_cov);
129 double locu = tagtrk.getD0();
130 double locv = tagtrk.getZ0();
131 double covuu =
132 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0);
133 double covvv =
134 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1);
135
136 ldmx::Measurement pseudo_meas;
137 pseudo_meas.setLocalPosition(locu, locv);
138 Acts::Vector3 dummy{0., 0., 0.};
139 Acts::Vector2 local_pos{locu, locv};
140 Acts::Vector3 global_pos =
141 tgt_surf->localToGlobal(geometryContext(), local_pos, dummy);
142
143 pseudo_meas.setGlobalPosition(global_pos(0), global_pos(1),
144 global_pos(2));
145 pseudo_meas.setTime(0.);
146 pseudo_meas.setLocalCovariance(covuu, covvv);
147
148 target_pseudo_meas.push_back(pseudo_meas);
149 }
150 }
151
152 if (event.exists(sim_particles_coll_name_, sim_particles_event_passname_)) {
153 particle_map = event.getMap<int, ldmx::SimParticle>(
154 sim_particles_coll_name_, sim_particles_passname_);
155 truth_matching_tool_->setup(particle_map, measurements);
156 }
157
158 ldmx_log(debug) << "Preparing the strategies";
159
160 groups_map_.clear();
161 // set the seeding strategy
162 // strategy is a list of layers from which to make the seed
163 // this must include 5 layers; layer_ numbering starts at 0.
164 // std::vector<int> strategy = {9,10,11,12,13};
165 std::vector<int> strategy = {0, 1, 2, 3, 4};
166 bool success = groupStrips(measurements, strategy);
167 if (success) findSeedsFromMap(seed_tracks, target_pseudo_meas);
168
169 // currently, we only use a single strategy but eventually
170 // we will use more. Below is an example of how to add them
171 /*
172 groups_map.clear();
173 strategy = {9,10,11,12,13};
174 success = GroupStrips(measurements,strategy);
175 if (success)
176 FindSeedsFromMap(seed_tracks, target_pseudo_meas);
177 */
178
179 groups_map_.clear();
180 // output_tree_->Fill();
181 ntracks_ += seed_tracks.size();
182 event.add(out_seed_collection_, seed_tracks);
183
184 auto end = std::chrono::high_resolution_clock::now();
185
186 // long long microseconds =
187 // std::chrono::duration_cast<std::chrono::microseconds>(end-start).count();
188
189 auto diff = end - start;
190 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
191
192 // Seed finding using 2D Hits
193 // - The hits should keep track if they are already associated to a track or
194 // not. This can be used for subsequent passes of seed-finding
195
196 // This should go into a digitization producer, which takes care of producing
197 // measurements from:
198 // - raw hits in data
199 // - sim hits in MC
200 // Step 0: Get the sim hits and project them on the surfaces to mimic 2d
201 // hits Step 1: Smear the hits and associate an uncertainty to those
202 // measurements.
203
204 xhit_.clear();
205 yhit_.clear();
206 zhit_.clear();
207
208 b0_.clear();
209 b1_.clear();
210 b2_.clear();
211 b3_.clear();
212 b4_.clear();
213
214} // produce
215
216// Seed finder from Robert's in HPS
217// https://github.com/JeffersonLab/hps-java/blob/47712878302eb0c0374d077a208a6f8f0e2c3dc6/tracking/src/main/java/org/hps/recon/tracking/kalman/SeedTrack.java
218// Adapted to possible 3D hit points.
219
220// yOrigin is the location along the beam about which we fit the seed helix
221// perigee_location is where the track parameters will be extracted
222
223// while this takes in a target measurement (from tagger, this is pmeas_tgt)
224// this code doesn't do anything with it yet.
225
226ldmx::Track SeedFinderProcessor::seedTracker(
227 const ldmx::Measurements& vmeas, double xOrigin,
228 const Acts::Vector3& perigee_location,
229 const ldmx::Measurements& pmeas_tgt) {
230 // Fit a straight line in the non-bending plane and a parabola in the bending
231 // plane
232
233 // Each measurement is treated as a 3D point, where the v direction is in the
234 // center of the strip with sigma equal to the length of the strip / sqrt(12).
235 // In this way it's easier to incorporate the tagger track extrapolation to
236 // the fit
237
238 Acts::Matrix<5, 5> a = Acts::Matrix<5, 5>::Zero();
239 Acts::Vector<5> y = Acts::Vector<5>::Zero();
240
241 for (auto meas : vmeas) {
242 double xmeas = meas.getGlobalPosition()[0] - xOrigin;
243
244 // Get the surface
245 const Acts::Surface* hit_surface = geometry().getSurface(meas.getLayerID());
246
247 // Get the global to local transformation
248 auto rot =
249 hit_surface->localToGlobalTransform(geometryContext()).rotation();
250 auto tr =
251 hit_surface->localToGlobalTransform(geometryContext()).translation();
252
253 auto rotl2g = rot.transpose();
254
255 // Only for saving purposes
256 Acts::Vector2 loc{meas.getLocalPosition()[0], 0.};
257
258 xhit_.push_back(xmeas);
259 yhit_.push_back(meas.getGlobalPosition()[1]);
260 zhit_.push_back(meas.getGlobalPosition()[2]);
261
262 Acts::Matrix<2, 5> a_i;
263
264 a_i(0, 0) = rotl2g(0, 1);
265 a_i(0, 1) = rotl2g(0, 1) * xmeas;
266 a_i(0, 2) = rotl2g(0, 1) * xmeas * xmeas;
267 a_i(0, 3) = rotl2g(0, 2);
268 a_i(0, 4) = rotl2g(0, 2) * xmeas;
269
270 a_i(1, 0) = rotl2g(1, 1);
271 a_i(1, 1) = rotl2g(1, 1) * xmeas;
272 a_i(1, 2) = rotl2g(1, 1) * xmeas * xmeas;
273 a_i(1, 3) = rotl2g(1, 2);
274 a_i(1, 4) = rotl2g(1, 2) * xmeas;
275
276 // Fill the yprime vector
277 Acts::Vector2 offset = (rot.transpose() * tr).topRows<2>();
278 Acts::Vector2 xoffset = {rotl2g(0, 0) * xmeas, rotl2g(1, 0) * xmeas};
279
280 loc(0) = meas.getLocalPosition()[0];
281 loc(1) = 0.;
282 // weight matrix
283 Acts::Matrix<2, 2> w_i = Acts::Matrix<2, 2>::Zero();
284
285 w_i(0, 0) = 1. / (u_error_ * u_error_);
286 w_i(1, 1) = 1. / (v_error_ * v_error_);
287
288 Acts::Vector2 yprime_i = loc + offset - xoffset;
289 y += (a_i.transpose()) * w_i * yprime_i;
290
291 Acts::Matrix<2, 5> wa_i = (w_i * a_i);
292 a += a_i.transpose() * wa_i;
293 }
294
295 Acts::Vector<5> b;
296 b = a.inverse() * y;
297
298 b0_.push_back(b(0));
299 b1_.push_back(b(1));
300 b2_.push_back(b(2));
301 b3_.push_back(b(3));
302 b4_.push_back(b(4));
303
304 // Acts::Vector<5> hlx = Acts::Vector<5>::Zero();
305 Acts::Vector<3> ref{0., 0., 0.};
306
307 // relative_perigee_x is the perigee position in the fit frame (fit-x = ACTS x
308 // - xOrigin). It is used only for evaluating the fitted curve (y, z, slopes).
309 // The PerigeeSurface and seed_pos must use the absolute ACTS x coordinate,
310 // which is perigee_location(0) directly.
311 double relative_perigee_x = perigee_location(0) - xOrigin;
312
313 std::shared_ptr<const Acts::PerigeeSurface> seed_perigee =
314 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
315 perigee_location(0), perigee_location(1), perigee_location(2)));
316
317 // in mm — x is absolute ACTS x; y and z evaluated at fit-x =
318 // relative_perigee_x
319 Acts::Vector3 seed_pos{perigee_location(0),
320 b(0) + b(1) * relative_perigee_x +
321 b(2) * relative_perigee_x * relative_perigee_x,
322 b(3) + b(4) * relative_perigee_x};
323 Acts::Vector3 dir{1, b(1) + 2 * b(2) * relative_perigee_x, b(4)};
324 dir /= dir.norm();
325
326 // Momentum at xmeas
327 // R in meters, p in GeV
328 double p = 0.3 * bfield_ * (1. / (2. * abs(b(2)))) * 0.001;
329 // std::cout<<"Momentum "<< p*dir << std::endl;
330
331 // Convert it to MeV since that's what TrackUtils assumes
332 Acts::Vector3 seed_mom = p * dir / Acts::UnitConstants::MeV;
333 double q =
334 b(2) < 0 ? -1 * Acts::UnitConstants::e : +1 * Acts::UnitConstants::e;
335
336 // Linear intersection with the perigee line. TODO:: Use propagator instead
337 // Project the position on the surface.
338 // This is mainly necessary for the perigee surface, where
339 // the mean might not fulfill the perigee condition.
340
341 // mg Aug 2024 .. interect has changed, but just remove boundary check
342 // and change intersection to intersections
343 // auto intersection =
344 // (*seed_perigee).intersect(geometry_context(), seed_pos, dir, false);
345
346 // Acts::FreeVector seed_free = tracking::sim::utils::toFreeParameters(
347 // intersection.intersection.position, seed_mom, q);
348
349 auto intersection =
350 (*seed_perigee).intersect(geometryContext(), seed_pos, dir);
351
352 Acts::FreeVector seed_free = tracking::sim::utils::toFreeParameters(
353 intersection[0].position(), seed_mom, q);
354
355 auto bound_params = Acts::transformFreeToBoundParameters(
356 seed_free, *seed_perigee, geometryContext())
357 .value();
358
359 ldmx_log(trace) << "bound parameters at perigee location" << bound_params;
360
361 Acts::BoundVector stddev;
362 // sigma set to 75% of momentum
363 double sigma_p = 0.75 * p * Acts::UnitConstants::GeV;
364 stddev[Acts::eBoundLoc0] =
365 inflate_factors_[Acts::eBoundLoc0] * 2 * Acts::UnitConstants::mm;
366 stddev[Acts::eBoundLoc1] =
367 inflate_factors_[Acts::eBoundLoc1] * 5 * Acts::UnitConstants::mm;
368 stddev[Acts::eBoundPhi] =
369 inflate_factors_[Acts::eBoundPhi] * 5 * Acts::UnitConstants::degree;
370 stddev[Acts::eBoundTheta] =
371 inflate_factors_[Acts::eBoundTheta] * 5 * Acts::UnitConstants::degree;
372 stddev[Acts::eBoundQOverP] =
373 inflate_factors_[Acts::eBoundQOverP] * (1. / p) * (1. / p) * sigma_p;
374 stddev[Acts::eBoundTime] =
375 inflate_factors_[Acts::eBoundTime] * 1000 * Acts::UnitConstants::ns;
376
377 ldmx_log(debug)
378 << "Making covariance matrix as diagonal matrix with inflated terms";
379 Acts::BoundMatrix bound_cov = stddev.cwiseProduct(stddev).asDiagonal();
380
381 ldmx_log(debug) << "...now putting together the seed track ...";
382
383 ldmx::Track trk = ldmx::Track();
384 // Store the perigee surface position (absolute ACTS coordinates) converted to
385 // LDMX frame so CKFProcessor can reconstruct the same surface.
386 Acts::Vector3 perigee_ldmx =
387 tracking::sim::utils::acts2Ldmx(perigee_location);
388 trk.setPerigeeLocation(perigee_ldmx(0), perigee_ldmx(1), perigee_ldmx(2));
389 trk.setChi2(0.);
390 trk.setNhits(5);
391 trk.setNdf(0);
392 trk.setNsharedHits(0);
393 trk.setCharge(q < 0 ? -1 : 1);
394 std::vector<double> v_seed_params(
395 (bound_params).data(),
396 bound_params.data() + bound_params.rows() * bound_params.cols());
397 std::vector<double> v_seed_cov;
398 tracking::sim::utils::flatCov(bound_cov, v_seed_cov);
399 trk.setPerigeeParameters(v_seed_params);
400 trk.setPerigeeCov(v_seed_cov);
401
402 ldmx_log(debug)
403 << "...making the ParticleHypothesis ...assume electron for now";
404 auto part_hypo{Acts::ParticleHypothesis::electron()};
405
406 ldmx_log(debug) << "Making BoundTrackParameters seedParameters";
407 Acts::BoundTrackParameters seed_parameters(
408 seed_perigee, std::move(bound_params), bound_cov, part_hypo);
409
410 ldmx_log(debug) << "Returning seed track";
411 return trk;
412}
413
415 // output_file_->cd();
416 // output_tree_->Write();
417 // output_file_->Close();
418 ldmx_log(info) << "AVG Time/Event: " << std::fixed << std::setprecision(1)
419 << processing_time_ / nevents_ << " ms";
420 ldmx_log(info) << "Total Seeds/Events: " << ntracks_ << "/" << nevents_;
421 ldmx_log(info) << "Seeds discarded due to multiple hits on layers "
422 << ndoubles_;
423 ldmx_log(info) << "not enough seed points " << nmissing_;
424 ldmx_log(info) << " nfailpmin=" << nfailpmin_;
425 ldmx_log(info) << " nfailpmax=" << nfailpmax_;
426 ldmx_log(info) << " nfaild0max=" << nfaild0max_;
427 ldmx_log(info) << " nfaild0min=" << nfaild0min_;
428 ldmx_log(info) << " nfailphicut=" << nfailphi_;
429 ldmx_log(info) << " nfailthetacut=" << nfailtheta_;
430 ldmx_log(info) << " nfailz0max=" << nfailz0max_;
431}
432
433// Given a strategy, group the hits according to some options
434// Not a good algorithm. The best would be to organize all the hits in sensors
435// *first* then only select the hits that we are interested into. TODO!
436
437bool SeedFinderProcessor::groupStrips(
438 const std::vector<ldmx::Measurement>& measurements,
439 const std::vector<int> strategy) {
440 // std::cout<<"Using stratedy"<<std::endl;
441 // for (auto& e : strategy) {
442 // std::cout<<e<<" ";
443 //}
444 // std::cout<<std::endl;
445
446 for (auto& meas : measurements) {
447 ldmx_log(trace) << meas;
448
449 if (std::find(strategy.begin(), strategy.end(), meas.getLayer()) !=
450 strategy.end()) {
451 ldmx_log(debug) << "Adding measurement from layer_ = " << meas.getLayer();
452 groups_map_[meas.getLayer()].push_back(&meas);
453 }
454
455 } // loop meas
456
457 if (groups_map_.size() < 5)
458 return false;
459 else
460 return true;
461}
462
463// For each strategy, form all the possible combinatorics and form a seedTrack
464// for each of those This will reshuffle all points. (issue?) Will sort the
465// meas_for_seed vector
466
467void SeedFinderProcessor::findSeedsFromMap(std::vector<ldmx::Track>& seeds,
468 const ldmx::Measurements& pmeas) {
469 std::map<int, std::vector<const ldmx::Measurement*>>::iterator groups_iter =
470 groups_map_.begin();
471 // Vector of iterators
472 constexpr size_t k = 5;
473 std::vector<std::vector<const ldmx::Measurement*>::iterator> it;
474 it.reserve(k);
475
476 unsigned int ikey = 0;
477 for (auto& key : groups_map_) {
478 it[ikey] = key.second.begin();
479 ikey++;
480 }
481
482 // K vectors in an array v[0],v[1].... v[K-1]
483
484 // Loop over all combinations
485 while (it[0] != groups_iter->second.end()) {
486 // process the pointed-to elements
487
488 /*
489 for (int j=0; j<K; j++) {
490 const ldmx::Measurement* meas = (*(it[j]));
491 std::cout<<meas->getGlobalPosition()[0]<<","
492 <<meas->getGlobalPosition()[1]<<","
493 <<meas->getGlobalPosition()[2]<<","<<std::endl;
494 }
495 */
496
497 std::vector<ldmx::Measurement> meas_for_seeds;
498 meas_for_seeds.reserve(5);
499
500 ldmx_log(debug) << " Grouping ";
501
502 for (int j = 0; j < k; j++) {
503 const ldmx::Measurement* meas = (*(it[j]));
504 meas_for_seeds.push_back(*meas);
505 }
506
507 std::sort(meas_for_seeds.begin(), meas_for_seeds.end(),
508 [](const ldmx::Measurement& m1, const ldmx::Measurement& m2) {
509 return m1.getGlobalPosition()[0] < m2.getGlobalPosition()[0];
510 });
511
512 if (meas_for_seeds.size() < 5) {
513 nmissing_++;
514 return;
515 }
516
517 ldmx_log(debug) << "making seedTrack";
518
519 Acts::Vector3 perigee{perigee_location_[0], perigee_location_[1],
521
522 ldmx::Track seed_track =
523 seedTracker(meas_for_seeds, meas_for_seeds.at(2).getGlobalPosition()[0],
524 perigee, pmeas);
525
526 bool fail = false;
527
528 // Remove failed fits
529 if (1. / abs(seed_track.getQoP()) < pmin_) {
530 nfailpmin_++;
531 fail = true;
532 } else if (1. / abs(seed_track.getQoP()) > pmax_) {
533 nfailpmax_++;
534 fail = true;
535 }
536
537 // Remove large part of fake tracks and duplicates with the following cuts
538 // for various compatibility checks.
539
540 else if (abs(seed_track.getZ0()) > z0max_) {
541 nfailz0max_++;
542 fail = true;
543 } else if (seed_track.getD0() < d0min_) {
544 nfaild0min_++;
545 fail = true;
546 } else if (seed_track.getD0() > d0max_) {
547 nfaild0max_++;
548 fail = true;
549 } else if (abs(seed_track.getPhi()) > phicut_) {
550 fail = true;
551 nfailphi_++;
552 } else if (abs(seed_track.getTheta() - piover2_) > thetacut_) {
553 fail = true;
554 nfailtheta_++;
555 }
556
557 // If I didn't use the target pseudo measurements in the track finding
558 // I can use them for compatibility with the tagger track
559
560 // TODO this should protect against running this check on tagger seeder.
561 // This is true only if this seeder is not run twice on the tagger after
562 // already having tagger tracks available.
563 if (pmeas.size() > 0) {
564 // I can have multiple target pseudo measurements
565 // A seed is rejected if it is found incompatible with all the target
566 // extrapolations
567
568 // This is set but unused, eventually we will use tagger track position at
569 // target to inform recoil tracking bool tgt_compatible = false;
570 for (auto tgt_pseudomeas : pmeas) {
571 // The d0/z0 are in a frame with the same orientation of the target
572 // surface
573 double delta_loc0 =
574 seed_track.getD0() - tgt_pseudomeas.getLocalPosition()[0];
575 double delta_loc1 =
576 seed_track.getZ0() - tgt_pseudomeas.getLocalPosition()[1];
577
578 if (abs(delta_loc0) < loc0cut_ && abs(delta_loc1) < loc1cut_) {
579 // found at least 1 compatible target location
580 // tgt_compatible = true;
581 break;
582 }
583 }
584 } // pmeas > 0
585
586 if (!fail) {
587 if (truth_matching_tool_->configured()) {
588 auto truth_info = truth_matching_tool_->truthMatch(meas_for_seeds);
589 seed_track.setTrackID(truth_info.track_id_);
590 seed_track.setPdgID(truth_info.pdg_id_);
591 seed_track.setTruthProb(truth_info.truth_prob_);
592 }
593
594 seeds.push_back(seed_track);
595 }
596
597 else {
598 b0_.pop_back();
599 b1_.pop_back();
600 b2_.pop_back();
601 b3_.pop_back();
602 b4_.pop_back();
603 }
604
605 // Go to next combination
606 ldmx_log(debug) << "Go to the next combination";
607
608 ++it[k - 1];
609 for (int i = k - 1;
610 (i > 0) && (it[i] == (std::next(groups_iter, i))->second.end()); --i) {
611 it[i] = std::next(groups_iter, i)->second.begin();
612 ++it[i - 1];
613 }
614 }
615} // find seeds
616
617} // namespace reco
618} // namespace tracking
619
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
std::string getName() const
Get the processor name.
Implements an event buffer system for storing event data.
Definition Event.h:42
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Definition Event.cxx:105
Class which represents the process under execution.
Definition Process.h:37
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
void setLocalPosition(const float &meas_u, const float &meas_v)
Set the local position i.e.
Definition Measurement.h:60
void setGlobalPosition(const float &meas_x, const float &meas_y, const float &meas_z)
Set the global position i.e.
Definition Measurement.h:41
void setLocalCovariance(const float &cov_uu, const float &cov_vv)
Set cov(U,U) and cov(V, V).
Definition Measurement.h:76
void setTime(const float &meas_t)
Set the measurement time in ns.
Definition Measurement.h:92
Class representing a simulated particle.
Definition SimParticle.h:24
Implementation of a track object.
Definition Track.h:53
SeedFinderProcessor(const std::string &name, framework::Process &process)
Constructor.
std::string out_seed_collection_
The name of the output collection of seeds to be stored.
double pmax_
Maximum cut on the momentum of the seeds.
std::vector< std::string > strategies_
List of stragies for seed finding.
std::string input_hits_collection_
The name of the input hits collection to use in finding seeds..
void onProcessEnd() override
Callback for the EventProcessor to take any necessary action when the processing of events finishes,...
void produce(framework::Event &event) override
Run the processor and create a collection of results which indicate if a charge particle can be found...
void onProcessStart() override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...
double pmin_
Minimum cut on the momentum of the seeds.
std::string tagger_trks_collection_
The name of the tagger Tracks (only for Recoil Seeding)
std::vector< double > perigee_location_
Location of the perigee for the helix track parameters.
double d0max_
Max d0 allowed for the seeds.
void configure(framework::config::Parameters &parameters) override
Configure the processor using the given user specified parameters.
double d0min_
Min d0 allowed for the seeds.
double z0max_
Max z0 allowed for the seeds.
a helper base class providing some methods to shorten access to common conditions used within the tra...
The measurement calibrator can be a function or a class/struct able to retrieve the sim hits containe...