LDMX Software
GSFProcessor.cxx
1#include "Tracking/Reco/GSFProcessor.h"
2
3#include <algorithm>
4
5#include "Acts/EventData/SourceLink.hpp"
6
7namespace tracking {
8namespace reco {
9
10GSFProcessor::GSFProcessor(const std::string& name, framework::Process& process)
11 : TrackingGeometryUser(name, process) {}
12
14 // Custom transformation of the interpolated bfield map
15 bool debug_transform = false;
16 auto transform_pos = [debug_transform](const Acts::Vector3& pos_) {
17 Acts::Vector3 rot_pos;
18 rot_pos(0) = pos_(1);
19 rot_pos(1) = pos_(2);
20 rot_pos(2) = pos_(0) + DIPOLE_OFFSET;
21
22 // Apply A rotation around the center of the magnet. (I guess offset first
23 // and then rotation)
24
25 if (debug_transform) {
26 std::cout << "PF::DEFAULT3 TRANSFORM" << std::endl;
27 std::cout << "PF::Check:: transforming Pos" << std::endl;
28 std::cout << pos_ << std::endl;
29 std::cout << "TO" << std::endl;
30 std::cout << rot_pos << std::endl;
31 }
32
33 return rot_pos;
34 };
35
36 Acts::RotationMatrix3 rotation = Acts::RotationMatrix3::Identity();
37 double scale = 1.;
38
39 auto transform_b_field = [rotation, scale, debug_transform](
40 const Acts::Vector3& field,
41 const Acts::Vector3& /*pos_*/) {
42 // Rotate the field in tracking coordinates
43 Acts::Vector3 rot_field;
44 rot_field(0) = field(2);
45 rot_field(1) = field(0);
46 rot_field(2) = field(1);
47
48 // Scale the field
49 rot_field = scale * rot_field;
50
51 // Rotate the field
52 rot_field = rotation * rot_field;
53
54 // A distortion scaled by position.
55
56 if (debug_transform) {
57 std::cout << "PF::DEFAULT3 TRANSFORM" << std::endl;
58 std::cout << "PF::Check:: transforming" << std::endl;
59 std::cout << field << std::endl;
60 std::cout << "TO" << std::endl;
61 std::cout << rot_field << std::endl;
62 }
63
64 return rot_field;
65 };
66
67 // Setup a interpolated bfield map
68 const auto map = std::make_shared<InterpolatedMagneticField3>(
69 loadDefaultBField(field_map_,
70 // default_transformPos,
71 // default_transformBField));
72 transform_pos, transform_b_field));
73
74 auto acts_logging_level = Acts::Logging::ERROR;
75
76 if (debug_) acts_logging_level = Acts::Logging::VERBOSE;
77
78 // Setup the GSF Fitter
79
80 // Stepper
81 // Acts::MixtureReductionMethod finalReductionMethod;
82 // const auto multi_stepper = Acts::MultiEigenStepperLoop{map};
83
84 // Acts::ComponentMergeMethod reductionMethod =
85 // Acts::ComponentMergeMethod::eMaxWeight;
86 // Acts::MultiEigenStepperLoop multi_stepper(
87 // map, reductionMethod,
88 // Acts::getDefaultLogger("GSF_STEP", acts_loggingLevel));
89
90 Acts::MultiEigenStepperLoop multi_stepper(map);
91 // Detailed Stepper
92
93 // Acts::MultiEigenStepperLoop multi_stepper(map, finalReductionMethod);
94
95 // Navigator
96 Acts::Navigator::Config nav_cfg{geometry().getTG()};
97 nav_cfg.resolveMaterial = true;
98 nav_cfg.resolvePassive = false;
99 nav_cfg.resolveSensitive = true;
100 const Acts::Navigator navigator(nav_cfg);
101
102 auto gsf_propagator =
103 GsfPropagator(std::move(multi_stepper), std::move(navigator),
104 Acts::getDefaultLogger("GSF_PROP", acts_logging_level));
105
106 BetheHeitlerApprox bethe_heitler = Acts::makeDefaultBetheHeitlerApprox();
107
108 const auto gsf_logger = Acts::getDefaultLogger("GSF", acts_logging_level);
109
110 gsf_ = std::make_unique<std::decay_t<decltype(*gsf_)>>(
111 std::move(gsf_propagator), std::move(bethe_heitler),
112 Acts::getDefaultLogger("GSF", acts_logging_level));
113
114 const auto stepper = Acts::EigenStepper<>{map};
115 propagator_ = std::make_unique<Propagator>(
116 stepper, navigator, Acts::getDefaultLogger("PROP", acts_logging_level));
117
118 trk_extrap_ = std::make_shared<std::decay_t<decltype(*trk_extrap_)>>(
119 *propagator_, geometryContext(), magneticFieldContext());
120}
121
123 out_trk_collection_ =
124 parameters.get<std::string>("out_trk_collection", "GSFTracks");
125
126 track_collection_ =
127 parameters.get<std::string>("trackCollection", "TaggerTracks");
128 meas_collection_ =
129 parameters.get<std::string>("measCollection", "DigiTaggerSimHits");
130
131 track_passname_ = parameters.get<std::string>("track_passname");
132 meas_passname_ = parameters.get<std::string>("meas_passname");
133 track_collection_event_passname_ =
134 parameters.get<std::string>("track_collection_event_passname");
135 meas_collection_event_passname_ =
136 parameters.get<std::string>("meas_collection_event_passname");
137
138 max_components_ = parameters.get<int>("maxComponents", 4);
139 abort_on_error_ = parameters.get<bool>("abortOnError", false);
140 disable_all_material_handling_ =
141 parameters.get<bool>("disableAllMaterialHandling", false);
142 weight_cutoff_ = parameters.get<double>("weight_cutoff_", 1.0e-4);
143
144 propagator_max_steps_ = parameters.get<int>("propagator_maxSteps", 10000);
145 propagator_step_size_ = parameters.get<double>("propagator_step_size", 200.);
146 field_map_ = parameters.get<std::string>("field_map");
147 use_perigee_ = parameters.get<bool>("usePerigee", false);
148
149 debug_ = parameters.get<bool>("debug", false);
150 tagger_tracking_ = parameters.get<bool>("taggerTracking", true);
151
152 // final_reduction_method_ =
153 // parameters.get<double>("finalReductionMethod",);
154}
155
157 // General Setup
158
159 auto tg{geometry()};
160
161 // Retrieve the tracks
162 if (!event.exists(track_collection_, track_collection_event_passname_))
163 return;
164 auto tracks{
165 event.getCollection<ldmx::Track>(track_collection_, track_passname_)};
166
167 // Retrieve the measurements
168 if (!event.exists(meas_collection_, meas_collection_event_passname_)) return;
169 auto measurements{
170 event.getCollection<ldmx::Measurement>(meas_collection_, meas_passname_)};
171
172 tracking::sim::LdmxMeasurementCalibrator calibrator{measurements};
173
174 // GSF Setup
175 Acts::GainMatrixUpdater updater;
176 Acts::GsfExtensions<Acts::VectorMultiTrajectory> gsf_extensions;
177 gsf_extensions.updater.connect<
178 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
179 &updater);
180 gsf_extensions.calibrator
182 Acts::VectorMultiTrajectory>>(&calibrator);
183
184 // Surface Accessor
185 struct SurfaceAccessor {
186 const Acts::TrackingGeometry* tracking_geometry_;
187
188 const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const {
189 const auto& index_source_link =
190 sourceLink.get<acts_examples::IndexSourceLink>();
191 return tracking_geometry_->findSurface(index_source_link.geometryId());
192 }
193 };
194
195 SurfaceAccessor m_sl_surface_accessor{tg.getTG().get()};
196 // m_slSurfaceAccessor.trackingGeometry = tg.getTG();
197 gsf_extensions.surfaceAccessor.connect<&SurfaceAccessor::operator()>(
198 &m_sl_surface_accessor);
199 gsf_extensions.mixtureReducer.connect<&Acts::reduceMixtureLargestWeights>();
200
201 // Propagator Options
202
203 // Move this at the start of the producer
204 Acts::PropagatorOptions<Acts::StepperPlainOptions,
205 Acts::NavigatorPlainOptions, ActionList, AbortList>
206 propagator_options(geometryContext(), magneticFieldContext());
207
208 propagator_options.pathLimit = std::numeric_limits<double>::max();
209
210 // Activate loop protection at some pt value
211 propagator_options.loopProtection =
212 false; //(startParameters.transverseMomentum() < cfg.ptLoopers);
213
214 // Switch the material interaction on/off & eventually into logging mode
215 auto& m_interactor =
216 propagator_options.actionList.get<Acts::MaterialInteractor>();
217 m_interactor.multipleScattering = true;
218 m_interactor.energyLoss = true;
219 m_interactor.recordInteractions = false;
220
221 // The logger can be switched to sterile, e.g. for timing logging
222 auto& s_logger =
223 propagator_options.actionList.get<Acts::detail::SteppingLogger>();
224 s_logger.sterile = true;
225 // Set a maximum step size
226 propagator_options.stepping.maxStepSize =
227 propagator_step_size_ * Acts::UnitConstants::mm;
228 propagator_options.maxSteps = propagator_max_steps_;
229
230 // Electron hypothesis
231 // propagator_options.mass = 0.511 * Acts::UnitConstants::MeV;
232
233 // GSF Options, to be moved out of produce loop
234
235 std::shared_ptr<const Acts::PerigeeSurface> origin_surface =
236 Acts::Surface::makeShared<Acts::PerigeeSurface>(
237 Acts::Vector3(0., 0., 0.));
238
239 std::shared_ptr<const Acts::PerigeeSurface> tagger_layer_surface =
240 Acts::Surface::makeShared<Acts::PerigeeSurface>(
241 Acts::Vector3(-700., 0., 0.));
242
243 std::shared_ptr<const Acts::PerigeeSurface> reference_surface =
244 origin_surface;
245 if (tagger_tracking_) {
246 reference_surface = tagger_layer_surface;
247 }
248
249 /*
250 Acts::GsfOptions<Acts::VectorMultiTrajectory> gsfOptions{
251 geometry_context(), magnetic_field_context(),
252 calibration_context(), gsf_extensions,
253 propagator_options, &(*origin_surface),
254 max_components_, weight_cutoff_,
255 abort_on_error_, disable_all_material_handling_};
256 */
257 Acts::GsfOptions<Acts::VectorMultiTrajectory> gsf_options{
258 geometryContext(), magneticFieldContext(), calibrationContext()};
259
260 gsf_options.extensions = gsf_extensions;
261 gsf_options.propagatorPlainOptions = propagator_options;
262 gsf_options.referenceSurface = &(*reference_surface);
263 gsf_options.maxComponents = max_components_;
264 gsf_options.weightCutoff = weight_cutoff_;
265 gsf_options.abortOnError = abort_on_error_;
266 gsf_options.disableAllMaterialHandling = disable_all_material_handling_;
267
268 // Output track container
269 std::vector<ldmx::Track> out_tracks;
270
271 // Acts containers
272 Acts::VectorTrackContainer vtc;
273 Acts::VectorMultiTrajectory mtj;
274 Acts::TrackContainer tc{vtc, mtj};
275
276 // Loop on tracks
277 unsigned int itrk = 0;
278
279 for (auto& track : tracks) {
280 // Retrieve measurements on track
281 std::vector<ldmx::Measurement> meas_on_track;
282
283 // std::vector<ActsExamples::IndexSourceLink> fit_trackSourceLinks;
284 std::vector<Acts::SourceLink> fit_track_source_links;
285
286 for (auto imeas : track.getMeasurementsIdxs()) {
287 auto meas = measurements.at(imeas);
288 meas_on_track.push_back(meas);
289
290 // Retrieve the surface
291
292 const Acts::Surface* hit_surface =
293 tg.geo::TrackingGeometry::getSurface(meas.getLayerID());
294
295 // Store the index_ source link
296 acts_examples::IndexSourceLink idx_sl(hit_surface->geometryId(), imeas);
297 fit_track_source_links.push_back(Acts::SourceLink(idx_sl));
298 }
299
300 // Reverse the order of the vectors
301 std::reverse(meas_on_track.begin(), meas_on_track.end());
302 std::reverse(fit_track_source_links.begin(), fit_track_source_links.end());
303
304 for (auto m : meas_on_track) {
305 ldmx_log(debug) << "Measurement:\n" << m << "\n";
306 }
307
308 ldmx_log(debug) << "GSF Refitting";
309
310 // Get the track parameters
311
312 std::shared_ptr<Acts::PerigeeSurface> perigee =
313 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
314 track.getPerigeeX(), track.getPerigeeY(), track.getPerigeeZ()));
315
316 Acts::BoundTrackParameters trk_btp =
317 tracking::sim::utils::boundTrackParameters(track, perigee);
318
319 std::shared_ptr<Acts::Surface> beam_origin_surface =
320 tracking::sim::utils::unboundSurface(-700);
321
322 const std::shared_ptr<Acts::Surface> target_surface =
323 tracking::sim::utils::unboundSurface(0.);
324
325 const std::shared_ptr<Acts::Surface> ecal_surface =
326 tracking::sim::utils::unboundSurface(240.5);
327
328 Acts::BoundTrackParameters trk_btp_b_o =
329 tracking::sim::utils::boundTrackParameters(track, perigee);
330
331 if (tagger_tracking_) {
332 if (!track.getTrackState(ldmx::TrackStateType::AtBeamOrigin)
333 .has_value()) {
334 ldmx_log(warn) << "Failed retreiving AtBeamOrigin TrackState for "
335 "track. Skipping..";
336 continue;
337 }
338
339 auto ts = track.getTrackState(ldmx::TrackStateType::AtBeamOrigin).value();
340 trk_btp_b_o = tracking::sim::utils::btp(
341 ts, beam_origin_surface,
342 11); // 11 == electron PDGid...hardcode for now
343 } else {
344 if (!track.getTrackState(ldmx::TrackStateType::AtTarget).has_value()) {
345 ldmx_log(warn)
346 << "Failed retreiving AtTarget TrackState for track. Skipping..";
347 continue;
348 }
349 auto ts = track.getTrackState(ldmx::TrackStateType::AtTarget).value();
350 trk_btp_b_o = tracking::sim::utils::btp(ts, target_surface, 11);
351 }
352 const Acts::BoundVector& trkpars = trk_btp.parameters();
353 ldmx_log(debug) << "CKF Track parameters" << std::endl
354 << trkpars[0] << " " << trkpars[1] << " " << trkpars[2]
355 << " " << trkpars[3] << " " << trkpars[4] << " "
356 << trkpars[5] << std::endl
357 << "Perigee Surface" << std::endl
358 << track.getPerigeeX() << " " << track.getPerigeeY() << " "
359 << track.getPerigeeZ();
360
361 Acts::Vector3 trk_pos = trk_btp.position(geometryContext());
362
363 ldmx_log(debug) << trk_pos(0) << " " << trk_pos(1) << " " << trk_pos(2)
364 << std::endl;
365
366 const Acts::BoundVector& trkpars_b_o = trk_btp_b_o.parameters();
367 ldmx_log(debug) << "CKF BeamOrigin track parameters" << std::endl
368 << trkpars_b_o[0] << " " << trkpars_b_o[1] << " "
369 << trkpars_b_o[2] << " " << trkpars_b_o[3] << " "
370 << trkpars_b_o[4] << " " << trkpars_b_o[5] << " ";
371
372 Acts::Vector3 trk_pos_b_o = trk_btp_b_o.position(geometryContext());
373 ldmx_log(debug) << trk_pos_b_o(0) << " " << trk_pos_b_o(1) << " "
374 << trk_pos_b_o(2) << std::endl;
375
376 auto gsf_refit_result =
377 gsf_->fit(fit_track_source_links.begin(), fit_track_source_links.end(),
378 trk_btp_b_o, gsf_options, tc);
379
380 if (!gsf_refit_result.ok()) {
381 ldmx_log(warn) << "GSF re-fit failed" << std::endl;
382 continue;
383 }
384
385 if (tc.size() < 1) continue;
386
387 auto gsftrk = tc.getTrack(itrk);
388 calculateTrackQuantities(gsftrk);
389
390 const Acts::BoundVector& perigee_pars = gsftrk.parameters();
391 const Acts::BoundMatrix& trk_cov = gsftrk.covariance();
392 const Acts::Surface& perigee_surface = gsftrk.referenceSurface();
393
394 ldmx_log(debug)
395 << "Found track:" << std::endl
396 << "Track states " << gsftrk.nTrackStates() << std::endl
397 << perigee_pars[Acts::eBoundLoc0] << " "
398 << perigee_pars[Acts::eBoundLoc1] << " "
399 << perigee_pars[Acts::eBoundPhi] << " "
400 << perigee_pars[Acts::eBoundTheta] << " "
401 << perigee_pars[Acts::eBoundQOverP] << std::endl
402 << "Reference Surface" << std::endl
403 << " " << perigee_surface.transform(geometryContext()).translation()(0)
404 << " " << perigee_surface.transform(geometryContext()).translation()(1)
405 << " " << perigee_surface.transform(geometryContext()).translation()(2)
406 << std::endl;
407
408 ldmx::Track trk = ldmx::Track();
409
410 bool success = false;
411 if (tagger_tracking_) {
412 ldmx_log(debug) << "Target extrapolation";
413 ldmx::Track::TrackState ts_at_target;
414
415 success = trk_extrap_->trackStateAtSurface(
416 gsftrk, target_surface, ts_at_target, ldmx::TrackStateType::AtTarget);
417
418 if (success) trk.addTrackState(ts_at_target);
419 } else {
420 ldmx_log(debug) << "Ecal Extrapolation";
421 ldmx::Track::TrackState ts_at_ecal;
422 success = trk_extrap_->trackStateAtSurface(
423 gsftrk, ecal_surface, ts_at_ecal, ldmx::TrackStateType::AtECAL);
424
425 if (success) trk.addTrackState(ts_at_ecal);
426 }
427
428 trk.setPerigeeLocation(
429 perigee_surface.transform(geometryContext()).translation()(0),
430 perigee_surface.transform(geometryContext()).translation()(1),
431 perigee_surface.transform(geometryContext()).translation()(2));
432
433 trk.setChi2(gsftrk.chi2());
434 trk.setNhits(gsftrk.nMeasurements());
435 trk.setNdf(gsftrk.nMeasurements() - 5);
437 tracking::sim::utils::convertActsToLdmxPars(perigee_pars));
438 std::vector<double> v_trk_cov;
439 tracking::sim::utils::flatCov(trk_cov, v_trk_cov);
440 trk.setPerigeeCov(v_trk_cov);
441 Acts::Vector3 trk_momentum = gsftrk.momentum();
442 trk.setMomentum(trk_momentum(0), trk_momentum(1), trk_momentum(2));
443
444 // truth information
445 trk.setTrackID(track.getTrackID());
446 trk.setPdgID(track.getPdgID());
447 trk.setTruthProb(track.getTruthProb());
448
449 itrk++;
450
451 out_tracks.push_back(trk);
452
453 } // loop on tracks
454
455 event.add(out_trk_collection_, out_tracks);
456}
457
460
461} // namespace reco
462} // namespace tracking
463
#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
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:92
Class which represents the process under execution.
Definition Process.h:36
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
Run-specific configuration and data stored in its own output TTree alongside the event TTree in the o...
Definition RunHeader.h:57
Implementation of a track object.
Definition Track.h:53
void setPerigeeParameters(const std::vector< double > &par)
d_0 z_0 phi_0 theta q/p t
Definition Track.h:156
void produce(framework::Event &event) override
Run the processor.
void onProcessEnd() override
Callback for the EventProcessor to take any necessary action when the processing of events finishes,...
void configure(framework::config::Parameters &parameters) override
Configure the processor using the given user specified parameters.
GSFProcessor(const std::string &name, framework::Process &process)
Constructor.
void onProcessStart() override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...
void onNewRun(const ldmx::RunHeader &rh) override
onNewRun is the first function called for each processor after the conditions are fully configured an...
a helper base class providing some methods to shorten access to common conditions used within the tra...
void calibrate1d(const Acts::GeometryContext &, const Acts::CalibrationContext &, const Acts::SourceLink &genericSourceLink, typename traj_t::TrackStateProxy trackState) const
Find the measurement corresponding to the source link.
The measurement calibrator can be a function or a class/struct able to retrieve the sim hits containe...