Run the processor.
152 {
153 eventnr_++;
154
155 auto tg{geometry()};
156
157
158
159 std::vector<ldmx::Track> tracks;
160
161 auto start = std::chrono::high_resolution_clock::now();
162
163 nevents_++;
164
165 auto loggingLevel = Acts::Logging::DEBUG;
166 ACTS_LOCAL_LOGGER(
167 Acts::getDefaultLogger("LDMX Tracking Geometry Maker", loggingLevel));
168
169
170 Acts::PropagatorOptions<Acts::StepperPlainOptions,
171 Acts::NavigatorPlainOptions, ActionList, AbortList>
172 propagator_options(geometry_context(), magnetic_field_context());
173
174 propagator_options.pathLimit = std::numeric_limits<double>::max();
175
176 propagator_options.loopProtection = false;
177
178
179
180 auto& mInteractor =
181 propagator_options.actionList.get<Acts::MaterialInteractor>();
182 mInteractor.multipleScattering = true;
183 mInteractor.energyLoss = true;
184 mInteractor.recordInteractions = false;
185
186
187 auto& sLogger =
188 propagator_options.actionList.get<Acts::detail::SteppingLogger>();
189 sLogger.sterile = true;
190
191 propagator_options.stepping.maxStepSize =
192 propagator_step_size_ * Acts::UnitConstants::mm;
193 propagator_options.maxSteps = propagator_maxSteps_;
194
195
196
197
198
199
200
201
202
203 auto setup = std::chrono::high_resolution_clock::now();
204 profiling_map_["setup"] +=
205 std::chrono::duration<double, std::milli>(setup - start).count();
206
207 const std::vector<ldmx::Measurement> measurements =
209 input_pass_name_);
210
211
212 std::shared_ptr<tracking::sim::TruthMatchingTool> truthMatchingTool = nullptr;
213 std::map<int, ldmx::SimParticle> particleMap;
214
215 if (event.
exists(
"SimParticles")) {
216 ldmx_log(debug) << "Setting up track truth matching tool";
218 truthMatchingTool = std::make_shared<tracking::sim::TruthMatchingTool>(
219 particleMap, measurements);
220 }
221
222
223
224 const auto geoId_sl_map = makeGeoIdSourceLinkMap(tg, measurements);
225
226 auto hits = std::chrono::high_resolution_clock::now();
227 profiling_map_["hits"] +=
228 std::chrono::duration<double, std::milli>(hits - setup).count();
229
230
231
232
233 const std::vector<ldmx::Track> seed_tracks =
234 event.getCollection<
ldmx::Track>(seed_coll_name_, input_pass_name_);
235
236 ldmx_log(info) << "Number of " << seed_coll_name_
237 << " seed tracks = " << seed_tracks.size();
238
239 if (seed_tracks.empty()) {
240 std::vector<ldmx::Track> empty;
241 ldmx_log(info) << "No seed tracks, returning...";
242 event.add(out_trk_collection_, empty);
243 return;
244 }
245
246
247 std::vector<Acts::BoundTrackParameters> startParameters;
248
249 ldmx_log(debug) << "Transform the seed track to bound parameters";
250 int seed_track_index{0};
251 for (auto& seed : seed_tracks) {
252
253 std::shared_ptr<Acts::PerigeeSurface> perigeeSurface =
254 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
255 seed.getPerigeeX(), seed.getPerigeeY(), seed.getPerigeeZ()));
256
257 Acts::BoundVector paramVec;
258 paramVec << seed.getD0(), seed.getZ0(), seed.getPhi(), seed.getTheta(),
259 seed.getQoP(), seed.getT();
260
261 Acts::BoundSquareMatrix covMat =
262 tracking::sim::utils::unpackCov(seed.getPerigeeCov());
263
264 ldmx_log(debug) << " For seed index = " << seed_track_index
265 << ": Perigee X / Y / Z = " << seed.getPerigeeX() << " / "
266 << seed.getPerigeeY() << " / " << seed.getPerigeeZ()
267 << ", D0 = " << paramVec[0] << ", Z0 = " << paramVec[1]
268 << ", Phi = " << paramVec[2] << ", Theta = " << paramVec[3]
269 << ", QoP = " << paramVec[4] << ", Time = " << paramVec[5];
270
271 ldmx_log(debug) << " Cov matrix diagonal (" << covMat(0, 0) << ", "
272 << covMat(1, 1) << ", " << covMat(2, 2) << ")";
273
274
275 auto partHypo{Acts::SinglyChargedParticleHypothesis::electron()};
276 startParameters.push_back(
277 Acts::BoundTrackParameters(perigeeSurface, paramVec, covMat, partHypo));
278
279
281
282 seed_track_index++;
283 }
284
285 auto seeds = std::chrono::high_resolution_clock::now();
286 profiling_map_["seeds"] +=
287 std::chrono::duration<double, std::milli>(seeds - hits).count();
288
289 Acts::GainMatrixUpdater kfUpdater;
290
291
292
293
294 Acts::MeasurementSelector::Config measurementSelectorCfg = {
295
296 {Acts::GeometryIdentifier(), {{}, {outlier_pval_}, {1u}}},
297 };
298
299 Acts::MeasurementSelector measSel{measurementSelectorCfg};
300
302
303 Acts::CombinatorialKalmanFilterExtensions<TrackContainer> ckf_extensions;
304
305 if (use1Dmeasurements_) {
306 ckf_extensions.calibrator
308 Acts::VectorMultiTrajectory>>(&calibrator);
309 } else {
310 ckf_extensions.calibrator
312 Acts::VectorMultiTrajectory>>(&calibrator);
313 }
314
315 ckf_extensions.updater.connect<
316 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
317 &kfUpdater);
318
319 ckf_extensions.measurementSelector
320 .connect<&Acts::MeasurementSelector::select<Acts::VectorMultiTrajectory>>(
321 &measSel);
322
323 ldmx_log(debug) << "SourceLinkAccessor...";
324
325
326 struct SourceLinkAccIt {
327 using BaseIt = decltype(geoId_sl_map.begin());
328 BaseIt it;
329
330#pragma GCC diagnostic push
331#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
332
333 using difference_type = typename BaseIt::difference_type;
334 using iterator_category = typename BaseIt::iterator_category;
335
336 using value_type = Acts::SourceLink;
337 using pointer = typename BaseIt::pointer;
338 using reference = value_type&;
339#pragma GCC diagnostic pop
340
341 SourceLinkAccIt& operator++() {
342 ++it;
343 return *this;
344 }
345 bool operator==(const SourceLinkAccIt& other) const {
346 return it == other.it;
347 }
348 bool operator!=(const SourceLinkAccIt& other) const {
349 return !(*this == other);
350 }
351
352
353
354 value_type operator*() const { return value_type{it->second}; }
355 };
356
357 auto sourceLinkAccessor = [&](const Acts::Surface& surface)
358 -> std::pair<SourceLinkAccIt, SourceLinkAccIt> {
359 auto [begin, end] = geoId_sl_map.equal_range(surface.geometryId());
360 return {SourceLinkAccIt{begin}, SourceLinkAccIt{end}};
361 };
362
363 Acts::SourceLinkAccessorDelegate<SourceLinkAccIt> sourceLinkAccessorDelegate;
364 sourceLinkAccessorDelegate.connect<&decltype(sourceLinkAccessor)::operator(),
365 decltype(sourceLinkAccessor)>(
366 &sourceLinkAccessor);
367
368 ldmx_log(debug) << "Setting up surfaces...";
369
370 std::shared_ptr<const Acts::PerigeeSurface> origin_surface =
371 Acts::Surface::makeShared<Acts::PerigeeSurface>(
372 Acts::Vector3(0., 0., 0.));
373
374 ldmx_log(debug) << "About to run CKF...";
375
376
377 auto ckf_setup = std::chrono::high_resolution_clock::now();
378 profiling_map_["ckf_setup"] +=
379 std::chrono::duration<double, std::milli>(ckf_setup - seeds).count();
380
381 Acts::VectorTrackContainer vtc;
382 Acts::VectorMultiTrajectory mtj;
383 Acts::TrackContainer tc{vtc, mtj};
384
385
386
387 ldmx_log(debug) << "Loop on the track candidates";
388 for (size_t trackId = 0u; trackId < startParameters.size(); ++trackId) {
389 ldmx_log(debug) << "---------------------------";
390 ldmx_log(debug) << "Candidate Track ID = " << trackId;
391
392 const Acts::CombinatorialKalmanFilterOptions<SourceLinkAccIt,
393 TrackContainer>
394 ckfOptions(TrackingGeometryUser::geometry_context(),
395 TrackingGeometryUser::magnetic_field_context(),
396 TrackingGeometryUser::calibration_context(),
397 sourceLinkAccessorDelegate, ckf_extensions,
398 propagator_options, true ,
399 false );
400
401 ldmx_log(debug) << " Checking options: multiple scattering = "
402 << ckfOptions.multipleScattering
403 << " energy loss = " << ckfOptions.energyLoss;
404 auto results =
405 ckf_->findTracks(startParameters.at(trackId), ckfOptions, tc);
406
407 auto start_params = startParameters.at(trackId).parameters().transpose();
408 ldmx_log(debug)
409 << " Checking CKF success for track candidate with params: "
410 << " D0 = " << start_params[0] << " Z0 = " << start_params[1]
411 << ", Phi = " << start_params[2] << " Theta = " << start_params[3]
412 << ", QoP = " << start_params[4] << " Time = " << start_params[5];
413 if (not results.ok()) {
414 ldmx_log(debug) << " CKF failed!";
415 continue;
416 } else {
417 ldmx_log(debug) << " CKF succeded!";
418 }
419
420 auto& tracksFromSeed = results.value();
421 if (tracksFromSeed.size() != 1) {
422 ldmx_log(info) << " tracksFromSeed.size = " << tracksFromSeed.size();
423 }
424
425 for (auto& track : tracksFromSeed) {
426
427 Acts::smoothTrack(geometry_context(), track);
428
431
432
433 bool success = trk_extrap_->TrackStateAtSurface(
434 track, target_surface, tsAtTarget, ldmx::TrackStateType::AtTarget);
435
436 if (success) {
437 ldmx_log(debug) << " Successfully obtained TrackState at target";
438
439 ldmx_log(debug) << " Parameters At Target: Loc0 = "
440 << tsAtTarget.params[0] << ", Loc1 "
441 << tsAtTarget.params[1]
442 << ", phi = " << tsAtTarget.params[2]
443 << ", theta = " << tsAtTarget.params[3] << ", QoP "
444 << tsAtTarget.params[4];
445
446 trk.addTrackState(tsAtTarget);
447 } else {
448 ldmx_log(info) << " Could not extrapolate to target! nhits = "
449 << track.nMeasurements() << " Printing track states: ";
450 for (const auto ts : track.trackStatesReversed()) {
451 if (ts.hasSmoothed()) {
452 ldmx_log(info) << " Track momentum for smoothed track state = "
453 << 1 / ts.smoothed()[Acts::eBoundQOverP];
454 ldmx_log(info) << " Parameters: " << ts.smoothed().transpose();
455 } else {
456 ldmx_log(info) << " Track state not smoothed!";
457 }
458 }
459 ldmx_log(info) << " ...skipping this track candidate...";
460 continue;
461 }
462
463
464
465
466
467
468
469
470 Acts::BoundTrackParameters boundStateAtTarget =
471 tracking::sim::utils::btp(tsAtTarget, target_surface, 11);
472 track.setReferenceSurface(target_surface);
473 track.parameters() = boundStateAtTarget.parameters();
474
475
476
477 const Acts::BoundVector& track_pars = track.parameters();
478
479
480 ldmx_log(debug) << " Track parameters (at target): Loc0 = "
481 << track_pars[Acts::eBoundLoc0]
482 << ", Loc1 = " << track_pars[Acts::eBoundLoc1]
483 << ", Theta = " << track_pars[Acts::eBoundTheta]
484 << ", Phi = " << track_pars[Acts::eBoundPhi]
485 << ", chi2 = " << track.chi2()
486 << ", nHits = " << track.nMeasurements();
487
488
489 trk.setPerigeeLocation(0, 0, 0);
491 trk.setPerigeeCov(tsAtTarget.cov);
492
493 trk.setChi2(track.chi2());
494 trk.setNhits(track.nMeasurements());
495
496
497 trk.setNdf(track.nMeasurements() - 5);
498 trk.setNsharedHits(track.nSharedHits());
499
500 ldmx_log(debug) << " Track momentum: px = " << track.momentum()[0]
501 << " py = " << track.momentum()[1]
502 << " pz = " << track.momentum()[2];
503 trk.setMomentum(track.momentum()[0], track.momentum()[1],
504 track.momentum()[2]);
505
506
507 if ((trk.getNhits() <= min_hits_) || (abs(1. / trk.getQoP()) <= 0.05)) {
508 ldmx_log(debug)
509 << " > Track candidate did NOT meet the requirements: Nhits = "
510 << trk.getNhits() << " and p = " << abs(1. / trk.getQoP())
511 << " GeV";
512
513
514 continue;
515 }
516
517
518 ldmx_log(debug) << " Add measurements to the final track from "
519 << track.nTrackStates() << " TrackStates with "
520 << track.nMeasurements() << " measurements";
521
522 int trk_state_index{0};
523 for (const auto ts : track.trackStatesReversed()) {
524
525 ldmx_log(debug) << " Checking Track State index = "
526 << trk_state_index << " at location "
527 << ts.referenceSurface()
528 .transform(geometry_context())
529 .translation()
530 .transpose();
531
532 if (ts.hasSmoothed()) {
533 ldmx_log(debug) << " Smoothed track parameters: "
534 << ts.smoothed().transpose();
535
536
537 }
538
539
540 auto typeFlags = ts.typeFlags();
541
542 if (typeFlags.test(Acts::TrackStateFlag::MeasurementFlag) &&
543 ts.hasUncalibratedSourceLink()) {
545 ts.getUncalibratedSourceLink()
546 .template get<ActsExamples::IndexSourceLink>();
547
549 ldmx_log(debug) << " Adding measurement to ldmx::track with "
550 "source link index = "
552 ldmx_log(trace) << " Measurement:\n" << ldmx_meas;
553 trk.addMeasurementIndex(sl.
index());
554 } else {
555 ldmx_log(debug) << " This TrackState is not a measurement";
556 }
557 trk_state_index++;
558 }
559
560 ldmx_log(debug) << " Starting extrapolations";
561
562
563 const double ECAL_SCORING_PLANE = 240.5;
564 Acts::Vector3 pos(ECAL_SCORING_PLANE, 0., 0.);
565 Acts::Translation3 surf_translation(pos);
566 Acts::Transform3 surf_transform(surf_translation * surf_rotation);
567 const std::shared_ptr<Acts::PlaneSurface> ecal_surface =
568 Acts::Surface::makeShared<Acts::PlaneSurface>(surf_transform);
569
570
571
572 Acts::Vector3 pos_hcal(540.0, 0., 0.);
573 Acts::Translation3 surf_translation_hcal(pos_hcal);
574 Acts::Transform3 surf_transform_hcal(surf_translation_hcal *
575 surf_rotation);
576 const std::shared_ptr<Acts::PlaneSurface> hcal_surface =
577 Acts::Surface::makeShared<Acts::PlaneSurface>(surf_transform_hcal);
578
579
580 const std::shared_ptr<Acts::Surface> beamOrigin_surface =
581 tracking::sim::utils::unboundSurface(-700);
582
583 if (taggerTracking_) {
584 ldmx_log(debug) << " Beam Origin Extrapolation";
586 success = trk_extrap_->TrackStateAtSurface(
587 track, beamOrigin_surface, tsAtBeamOrigin,
588 ldmx::TrackStateType::AtBeamOrigin);
589
590 if (success) {
591 trk.addTrackState(tsAtBeamOrigin);
592 ldmx_log(debug)
593 << " Successfully obtained TrackState at beam origin";
594 }
595 }
596
597
598 if (!taggerTracking_) {
599 ldmx_log(debug) << " Ecal Extrapolation";
601 success = trk_extrap_->TrackStateAtSurface(
602 track, ecal_surface, tsAtEcal, ldmx::TrackStateType::AtECAL);
603
604 if (success) {
605 trk.addTrackState(tsAtEcal);
606 ldmx_log(debug) << " Successfully obtained TrackState at Ecal";
607 ldmx_log(debug) << " Parameters At Ecal: Loc0 = "
608 << tsAtEcal.params[0]
609 << ", Loc1 = " << tsAtEcal.params[1]
610 << ", phi = " << tsAtEcal.params[2]
611 << ", theta = " << tsAtEcal.params[3]
612 << ", QoP = " << tsAtEcal.params[4];
613 } else {
614 ldmx_log(info) << " Could not extrapolate to ECAL!! Please check "
615 "the track states";
616 }
617 }
618
619
620 if (!taggerTracking_) {
621 ldmx_log(debug) << " Hcal Extrapolation";
623 success = trk_extrap_->TrackStateAtSurface(
624 track, hcal_surface, tsAtHcal, ldmx::TrackStateType::AtHCAL);
625
626 if (success) {
627 trk.addTrackState(tsAtHcal);
628 ldmx_log(debug) << " Successfully obtained TrackState at Hcal";
629 ldmx_log(debug) << " Parameters At Hcal: Loc0 = "
630 << tsAtHcal.params[0]
631 << ", Loc1 = " << tsAtHcal.params[1]
632 << ", phi = " << tsAtHcal.params[2]
633 << ", theta = " << tsAtHcal.params[3]
634 << ", QoP = " << tsAtHcal.params[4];
635 } else {
636 ldmx_log(info) << " Could not extrapolate to HCAL!! Please check "
637 "the track states";
638 }
639 }
640
641
642 if (truthMatchingTool) {
643 auto truthInfo = truthMatchingTool->TruthMatch(trk);
644 trk.setTrackID(truthInfo.trackID);
645 trk.setPdgID(truthInfo.pdgID);
646 trk.setTruthProb(truthInfo.truthProb);
647 }
648
649
650 ldmx_log(debug)
651 << " > Adding the track candidate to the track collection";
652 tracks.push_back(trk);
653 ntracks_++;
654 }
655 }
656
657 ldmx_log(info) << "Number of CKF tracks " << tracks.size();
658
659 auto ckf_run = std::chrono::high_resolution_clock::now();
660 profiling_map_["ckf_run"] +=
661 std::chrono::duration<double, std::milli>(ckf_run - ckf_setup).count();
662
663
664 auto sharedHits = computeSharedHits(tracks, measurements, tg,
665 tracking::sim::utils::sourceLinkHash,
666 tracking::sim::utils::sourceLinkEquality);
667 for (std::size_t iTrack = 0; iTrack < sharedHits.size(); ++iTrack) {
668 tracks[iTrack].setNsharedHits(sharedHits[iTrack].size());
669 for (auto idx : sharedHits[iTrack]) {
670 tracks[iTrack].addSharedIndex(idx);
671 }
672 }
673
674 auto result_loop = std::chrono::high_resolution_clock::now();
675 profiling_map_["result_loop"] +=
676 std::chrono::duration<double, std::milli>(result_loop - ckf_run).count();
677
678
679 event.add(out_trk_collection_, tracks);
680
681 auto end = std::chrono::high_resolution_clock::now();
682
683
684 auto diff = end - start;
685 processing_time_ += std::chrono::duration<double, std::milli>(diff).count();
686}
constexpr Index index() const
Access the index.
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.
Class representing a simulated particle.
Implementation of a track object.
void setPerigeeParameters(const std::vector< double > &par)
d_0 z_0 phi_0 theta q/p t
void calibrate_1d(const Acts::GeometryContext &, const Acts::CalibrationContext &, const Acts::SourceLink &genericSourceLink, typename traj_t::TrackStateProxy trackState) const
Find the measurement corresponding to the source link.
void calibrate(const Acts::GeometryContext &, const Acts::CalibrationContext &, const Acts::SourceLink &genericSourceLink, typename traj_t::TrackStateProxy trackState) const
Find the measurement corresponding to the source link.