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 debugTransform = false;
16 auto transformPos = [debugTransform](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 (debugTransform) {
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 transformBField = [rotation, scale, debugTransform](
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 (debugTransform) {
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 transformPos, transformBField));
73
74 auto acts_loggingLevel = Acts::Logging::ERROR;
75
76 if (debug_) acts_loggingLevel = 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 navCfg{geometry().getTG()};
97 navCfg.resolveMaterial = true;
98 navCfg.resolvePassive = false;
99 navCfg.resolveSensitive = true;
100 const Acts::Navigator navigator(navCfg);
101
102 auto gsf_propagator =
103 GsfPropagator(std::move(multi_stepper), std::move(navigator),
104 Acts::getDefaultLogger("GSF_PROP", acts_loggingLevel));
105
106 BetheHeitlerApprox betheHeitler = Acts::makeDefaultBetheHeitlerApprox();
107
108 const auto gsfLogger = Acts::getDefaultLogger("GSF", acts_loggingLevel);
109
110 gsf_ = std::make_unique<std::decay_t<decltype(*gsf_)>>(
111 std::move(gsf_propagator), std::move(betheHeitler),
112 Acts::getDefaultLogger("GSF", acts_loggingLevel));
113
114 const auto stepper = Acts::EigenStepper<>{map};
115 propagator_ = std::make_unique<Propagator>(
116 stepper, navigator, Acts::getDefaultLogger("PROP", acts_loggingLevel));
117
118 trk_extrap_ = std::make_shared<std::decay_t<decltype(*trk_extrap_)>>(
119 *propagator_, geometry_context(), magnetic_field_context());
120}
121
123 out_trk_collection_ =
124 parameters.getParameter<std::string>("out_trk_collection", "GSFTracks");
125
126 trackCollection_ =
127 parameters.getParameter<std::string>("trackCollection", "TaggerTracks");
128 measCollection_ = parameters.getParameter<std::string>("measCollection",
129 "DigiTaggerSimHits");
130
131 maxComponents_ = parameters.getParameter<int>("maxComponents", 4);
132 abortOnError_ = parameters.getParameter<bool>("abortOnError", false);
133 disableAllMaterialHandling_ =
134 parameters.getParameter<bool>("disableAllMaterialHandling", false);
135 weightCutoff_ = parameters.getParameter<double>("weightCutoff_", 1.0e-4);
136
137 propagator_maxSteps_ =
138 parameters.getParameter<int>("propagator_maxSteps", 10000);
139 propagator_step_size_ =
140 parameters.getParameter<double>("propagator_step_size", 200.);
141 field_map_ = parameters.getParameter<std::string>("field_map");
142 usePerigee_ = parameters.getParameter<bool>("usePerigee", false);
143
144 debug_ = parameters.getParameter<bool>("debug", false);
145 taggerTracking_ = parameters.getParameter<bool>("taggerTracking", true);
146
147 // finalReductionMethod_ =
148 // parameters.getParameter<double>("finalReductionMethod",);
149}
150
152 // General Setup
153
154 auto tg{geometry()};
155
156 // Retrieve the tracks
157 if (!event.exists(trackCollection_)) return;
158 auto tracks{event.getCollection<ldmx::Track>(trackCollection_)};
159
160 // Retrieve the measurements
161 if (!event.exists(measCollection_)) return;
162 auto measurements{event.getCollection<ldmx::Measurement>(measCollection_)};
163
164 tracking::sim::LdmxMeasurementCalibrator calibrator{measurements};
165
166 // GSF Setup
167 Acts::GainMatrixUpdater updater;
168 Acts::GsfExtensions<Acts::VectorMultiTrajectory> gsf_extensions;
169 gsf_extensions.updater.connect<
170 &Acts::GainMatrixUpdater::operator()<Acts::VectorMultiTrajectory>>(
171 &updater);
172 gsf_extensions.calibrator
174 Acts::VectorMultiTrajectory>>(&calibrator);
175
176 // Surface Accessor
177 struct SurfaceAccessor {
178 const Acts::TrackingGeometry* trackingGeometry;
179
180 const Acts::Surface* operator()(const Acts::SourceLink& sourceLink) const {
181 const auto& indexSourceLink =
182 sourceLink.get<ActsExamples::IndexSourceLink>();
183 return trackingGeometry->findSurface(indexSourceLink.geometryId());
184 }
185 };
186
187 SurfaceAccessor m_slSurfaceAccessor{tg.getTG().get()};
188 // m_slSurfaceAccessor.trackingGeometry = tg.getTG();
189 gsf_extensions.surfaceAccessor.connect<&SurfaceAccessor::operator()>(
190 &m_slSurfaceAccessor);
191 gsf_extensions.mixtureReducer.connect<&Acts::reduceMixtureLargestWeights>();
192
193 // Propagator Options
194
195 // Move this at the start of the producer
196 Acts::PropagatorOptions<Acts::StepperPlainOptions,
197 Acts::NavigatorPlainOptions, ActionList, AbortList>
198 propagator_options(geometry_context(), magnetic_field_context());
199
200 propagator_options.pathLimit = std::numeric_limits<double>::max();
201
202 // Activate loop protection at some pt value
203 propagator_options.loopProtection =
204 false; //(startParameters.transverseMomentum() < cfg.ptLoopers);
205
206 // Switch the material interaction on/off & eventually into logging mode
207 auto& mInteractor =
208 propagator_options.actionList.get<Acts::MaterialInteractor>();
209 mInteractor.multipleScattering = true;
210 mInteractor.energyLoss = true;
211 mInteractor.recordInteractions = false;
212
213 // The logger can be switched to sterile, e.g. for timing logging
214 auto& sLogger =
215 propagator_options.actionList.get<Acts::detail::SteppingLogger>();
216 sLogger.sterile = true;
217 // Set a maximum step size
218 propagator_options.stepping.maxStepSize =
219 propagator_step_size_ * Acts::UnitConstants::mm;
220 propagator_options.maxSteps = propagator_maxSteps_;
221
222 // Electron hypothesis
223 // propagator_options.mass = 0.511 * Acts::UnitConstants::MeV;
224
225 // GSF Options, to be moved out of produce loop
226
227 std::shared_ptr<const Acts::PerigeeSurface> origin_surface =
228 Acts::Surface::makeShared<Acts::PerigeeSurface>(
229 Acts::Vector3(0., 0., 0.));
230
231 std::shared_ptr<const Acts::PerigeeSurface> tagger_layer_surface =
232 Acts::Surface::makeShared<Acts::PerigeeSurface>(
233 Acts::Vector3(-700., 0., 0.));
234
235 std::shared_ptr<const Acts::PerigeeSurface> reference_surface =
236 origin_surface;
237 if (taggerTracking_) {
238 reference_surface = tagger_layer_surface;
239 }
240
241 /*
242 Acts::GsfOptions<Acts::VectorMultiTrajectory> gsfOptions{
243 geometry_context(), magnetic_field_context(),
244 calibration_context(), gsf_extensions,
245 propagator_options, &(*origin_surface),
246 maxComponents_, weightCutoff_,
247 abortOnError_, disableAllMaterialHandling_};
248 */
249 Acts::GsfOptions<Acts::VectorMultiTrajectory> gsfOptions{
250 geometry_context(), magnetic_field_context(), calibration_context()};
251
252 gsfOptions.extensions = gsf_extensions;
253 gsfOptions.propagatorPlainOptions = propagator_options;
254 gsfOptions.referenceSurface = &(*reference_surface);
255 gsfOptions.maxComponents = maxComponents_;
256 gsfOptions.weightCutoff = weightCutoff_;
257 gsfOptions.abortOnError = abortOnError_;
258 gsfOptions.disableAllMaterialHandling = disableAllMaterialHandling_;
259
260 // Output track container
261 std::vector<ldmx::Track> out_tracks;
262
263 // Acts containers
264 Acts::VectorTrackContainer vtc;
265 Acts::VectorMultiTrajectory mtj;
266 Acts::TrackContainer tc{vtc, mtj};
267
268 // Loop on tracks
269 unsigned int itrk = 0;
270
271 for (auto& track : tracks) {
272 // Retrieve measurements on track
273 std::vector<ldmx::Measurement> measOnTrack;
274
275 // std::vector<ActsExamples::IndexSourceLink> fit_trackSourceLinks;
276 std::vector<Acts::SourceLink> fit_trackSourceLinks;
277
278 for (auto imeas : track.getMeasurementsIdxs()) {
279 auto meas = measurements.at(imeas);
280 measOnTrack.push_back(meas);
281
282 // Retrieve the surface
283
284 const Acts::Surface* hit_surface = tg.getSurface(meas.getLayerID());
285
286 // Store the index source link
287 ActsExamples::IndexSourceLink idx_sl(hit_surface->geometryId(), imeas);
288 fit_trackSourceLinks.push_back(Acts::SourceLink(idx_sl));
289 }
290
291 // Reverse the order of the vectors
292 std::reverse(measOnTrack.begin(), measOnTrack.end());
293 std::reverse(fit_trackSourceLinks.begin(), fit_trackSourceLinks.end());
294
295 for (auto m : measOnTrack) {
296 ldmx_log(debug) << "Measurement:\n" << m << "\n";
297 }
298
299 ldmx_log(debug) << "GSF Refitting";
300
301 // Get the track parameters
302
303 std::shared_ptr<Acts::PerigeeSurface> perigee =
304 Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3(
305 track.getPerigeeX(), track.getPerigeeY(), track.getPerigeeZ()));
306
307 Acts::BoundTrackParameters trk_btp =
308 tracking::sim::utils::boundTrackParameters(track, perigee);
309
310 std::shared_ptr<Acts::Surface> beamOrigin_surface =
311 tracking::sim::utils::unboundSurface(-700);
312
313 const std::shared_ptr<Acts::Surface> target_surface =
314 tracking::sim::utils::unboundSurface(0.);
315
316 const std::shared_ptr<Acts::Surface> ecal_surface =
317 tracking::sim::utils::unboundSurface(240.5);
318
319 Acts::BoundTrackParameters trk_btp_bO =
320 tracking::sim::utils::boundTrackParameters(track, perigee);
321
322 if (taggerTracking_) {
323 if (!track.getTrackState(ldmx::TrackStateType::AtBeamOrigin)
324 .has_value()) {
325 ldmx_log(warn) << "Failed retreiving AtBeamOrigin TrackState for "
326 "track. Skipping..";
327 continue;
328 }
329
330 auto ts = track.getTrackState(ldmx::TrackStateType::AtBeamOrigin).value();
331 trk_btp_bO = tracking::sim::utils::btp(
332 ts, beamOrigin_surface,
333 11); // 11 == electron PDGid...hardcode for now
334 } else {
335 if (!track.getTrackState(ldmx::TrackStateType::AtTarget).has_value()) {
336 ldmx_log(warn)
337 << "Failed retreiving AtTarget TrackState for track. Skipping..";
338 continue;
339 }
340 auto ts = track.getTrackState(ldmx::TrackStateType::AtTarget).value();
341 trk_btp_bO = tracking::sim::utils::btp(ts, target_surface, 11);
342 }
343 const Acts::BoundVector& trkpars = trk_btp.parameters();
344 ldmx_log(debug) << "CKF Track parameters" << std::endl
345 << trkpars[0] << " " << trkpars[1] << " " << trkpars[2]
346 << " " << trkpars[3] << " " << trkpars[4] << " "
347 << trkpars[5] << std::endl
348 << "Perigee Surface" << std::endl
349 << track.getPerigeeX() << " " << track.getPerigeeY() << " "
350 << track.getPerigeeZ();
351
352 Acts::Vector3 trk_pos = trk_btp.position(geometry_context());
353
354 ldmx_log(debug) << trk_pos(0) << " " << trk_pos(1) << " " << trk_pos(2)
355 << std::endl;
356
357 const Acts::BoundVector& trkpars_bO = trk_btp_bO.parameters();
358 ldmx_log(debug) << "CKF BeamOrigin track parameters" << std::endl
359 << trkpars_bO[0] << " " << trkpars_bO[1] << " "
360 << trkpars_bO[2] << " " << trkpars_bO[3] << " "
361 << trkpars_bO[4] << " " << trkpars_bO[5] << " ";
362
363 Acts::Vector3 trk_pos_bO = trk_btp_bO.position(geometry_context());
364 ldmx_log(debug) << trk_pos_bO(0) << " " << trk_pos_bO(1) << " "
365 << trk_pos_bO(2) << std::endl;
366
367 auto gsf_refit_result =
368 gsf_->fit(fit_trackSourceLinks.begin(), fit_trackSourceLinks.end(),
369 trk_btp_bO, gsfOptions, tc);
370
371 if (!gsf_refit_result.ok()) {
372 ldmx_log(warn) << "GSF re-fit failed" << std::endl;
373 continue;
374 }
375
376 if (tc.size() < 1) continue;
377
378 auto gsftrk = tc.getTrack(itrk);
379 calculateTrackQuantities(gsftrk);
380
381 const Acts::BoundVector& perigee_pars = gsftrk.parameters();
382 const Acts::BoundMatrix& trk_cov = gsftrk.covariance();
383 const Acts::Surface& perigee_surface = gsftrk.referenceSurface();
384
385 ldmx_log(debug)
386 << "Found track:" << std::endl
387 << "Track states " << gsftrk.nTrackStates() << std::endl
388 << perigee_pars[Acts::eBoundLoc0] << " "
389 << perigee_pars[Acts::eBoundLoc1] << " "
390 << perigee_pars[Acts::eBoundPhi] << " "
391 << perigee_pars[Acts::eBoundTheta] << " "
392 << perigee_pars[Acts::eBoundQOverP] << std::endl
393 << "Reference Surface" << std::endl
394 << " " << perigee_surface.transform(geometry_context()).translation()(0)
395 << " " << perigee_surface.transform(geometry_context()).translation()(1)
396 << " " << perigee_surface.transform(geometry_context()).translation()(2)
397 << std::endl;
398
399 ldmx::Track trk = ldmx::Track();
400
401 bool success = false;
402 if (taggerTracking_) {
403 ldmx_log(debug) << "Target extrapolation";
404 ldmx::Track::TrackState tsAtTarget;
405
406 success = trk_extrap_->TrackStateAtSurface(
407 gsftrk, target_surface, tsAtTarget, ldmx::TrackStateType::AtTarget);
408
409 if (success) trk.addTrackState(tsAtTarget);
410 } else {
411 ldmx_log(debug) << "Ecal Extrapolation";
413 success = trk_extrap_->TrackStateAtSurface(gsftrk, ecal_surface, tsAtEcal,
414 ldmx::TrackStateType::AtECAL);
415
416 if (success) trk.addTrackState(tsAtEcal);
417 }
418
419 trk.setPerigeeLocation(
420 perigee_surface.transform(geometry_context()).translation()(0),
421 perigee_surface.transform(geometry_context()).translation()(1),
422 perigee_surface.transform(geometry_context()).translation()(2));
423
424 trk.setChi2(gsftrk.chi2());
425 trk.setNhits(gsftrk.nMeasurements());
426 trk.setNdf(gsftrk.nMeasurements() - 5);
428 tracking::sim::utils::convertActsToLdmxPars(perigee_pars));
429 std::vector<double> v_trk_cov;
430 tracking::sim::utils::flatCov(trk_cov, v_trk_cov);
431 trk.setPerigeeCov(v_trk_cov);
432 Acts::Vector3 trk_momentum = gsftrk.momentum();
433 trk.setMomentum(trk_momentum(0), trk_momentum(1), trk_momentum(2));
434
435 // truth information
436 trk.setTrackID(track.getTrackID());
437 trk.setPdgID(track.getPdgID());
438 trk.setTruthProb(track.getTruthProb());
439
440 itrk++;
441
442 out_tracks.push_back(trk);
443
444 } // loop on tracks
445
446 event.add(out_trk_collection_, out_tracks);
447}
448
451
452} // namespace reco
453} // namespace tracking
454
455DECLARE_PRODUCER_NS(tracking::reco, GSFProcessor)
#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
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:27
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
Run-specific configuration and data stored in its own output TTree alongside the event TTree in the o...
Definition RunHeader.h:54
Implementation of a track object.
Definition Track.h:52
void setPerigeeParameters(const std::vector< double > &par)
d_0 z_0 phi_0 theta q/p t
Definition Track.h:144
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 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.
The measurement calibrator can be a function or a class/struct able to retrieve the sim hits containe...