LDMX Software
GreedyAmbiguitySolver.cxx
1#include "Tracking/Reco/GreedyAmbiguitySolver.h"
2
3#include <algorithm>
4
5#include "Acts/EventData/SourceLink.hpp"
6#include "Acts/EventData/TrackHelpers.hpp"
7
8namespace tracking {
9namespace reco {
10
12 framework::Process& process)
13 : TrackingGeometryUser(name, process) {}
14
15// Helper Functions
16
17/*
18std::size_t GreedyAmbiguitySolver::sourceLinkHash(const Acts::SourceLink& a) {
19 return static_cast<std::size_t>(
20 a.get<ActsExamples::IndexSourceLink>().index());
21 }
22
23bool GreedyAmbiguitySolver::sourceLinkEquality(const Acts::SourceLink& a, const
24Acts::SourceLink& b) { return a.get<ActsExamples::IndexSourceLink>().index() ==
25 b.get<ActsExamples::IndexSourceLink>().index();
26}
27*/
28
30 std::size_t iTrack) const {
31 for (auto iMeasurement : state.measurements_per_track[iTrack]) {
32 state.tracks_per_measurement[iMeasurement].erase(iTrack);
33 if (state.tracks_per_measurement[iMeasurement].size() == 1) {
34 auto jTrack = *state.tracks_per_measurement[iMeasurement].begin();
35 --state.shared_measurements_per_track[jTrack];
36 }
37 }
38 state.selected_tracks.erase(iTrack);
39}
40
41template <typename geometry_t, typename source_link_hash_t,
42 typename source_link_equality_t>
44 std::vector<ldmx::Track> tracks, std::vector<ldmx::Measurement> meas_coll,
45 State& state, geometry_t& tg, source_link_hash_t&& sourceLinkHash,
46 source_link_equality_t&& sourceLinkEquality) const {
47 auto measurementIndexMap =
48 std::unordered_map<Acts::SourceLink, std::size_t, source_link_hash_t,
49 source_link_equality_t>(0, sourceLinkHash,
50 sourceLinkEquality);
51
52 // auto tg{geometry()};
53 // Iterate through all input tracks, collect their properties like measurement
54 // count and chi2 and fill the measurement map in order to relate tracks to
55 // each other if they have shared hits.
56 state.number_of_tracks = 0;
57 for (const auto& track : tracks) {
58 // Kick out tracks that do not fulfill our initial requirements
59 if (track.getNhits() < n_meas_min_) {
60 continue;
61 }
62
63 std::vector<std::size_t> measurements;
64 for (auto imeas : track.getMeasurementsIdxs()) {
65 auto meas = meas_coll.at(imeas);
66 const Acts::Surface* hit_surface = tg.getSurface(meas.getLayerID());
67 // Store the index source link
68 ActsExamples::IndexSourceLink idx_sl(hit_surface->geometryId(), imeas);
69 Acts::SourceLink sourceLink = Acts::SourceLink(idx_sl);
70
71 auto emplace = measurementIndexMap.try_emplace(
72 sourceLink, measurementIndexMap.size());
73 measurements.push_back(emplace.first->second);
74 }
75
76 state.track_tips.push_back(state.number_of_tracks);
77 state.track_chi2.push_back(track.getChi2() / track.getNdf());
78 state.measurements_per_track.push_back(std::move(measurements));
79 state.selected_tracks.insert(state.number_of_tracks);
80
81 ++state.number_of_tracks;
82 }
83
84 // Now we relate measurements to tracks
85 for (std::size_t iTrack = 0; iTrack < state.number_of_tracks; ++iTrack) {
86 for (auto iMeasurement : state.measurements_per_track[iTrack]) {
87 state.tracks_per_measurement[iMeasurement].insert(iTrack);
88 }
89 }
90
91 // Finally, we can accumulate the number of shared measurements per track
92 state.shared_measurements_per_track =
93 std::vector<std::size_t>(state.track_tips.size(), 0);
94 for (std::size_t iTrack = 0; iTrack < state.number_of_tracks; ++iTrack) {
95 for (auto iMeasurement : state.measurements_per_track[iTrack]) {
96 if (state.tracks_per_measurement[iMeasurement].size() > 1) {
97 ++state.shared_measurements_per_track[iTrack];
98 }
99 }
100 }
101}
102
106 auto sharedMeasurementsComperator = [&state](std::size_t a, std::size_t b) {
107 return state.shared_measurements_per_track[a] <
108 state.shared_measurements_per_track[b];
109 };
110
114 auto trackComperator = [&state](std::size_t a, std::size_t b) {
116 auto relativeSharedMeasurements = [&state](std::size_t i) {
117 return 1.0 * state.shared_measurements_per_track[i] /
118 state.measurements_per_track[i].size();
119 };
120
121 if (relativeSharedMeasurements(a) != relativeSharedMeasurements(b)) {
122 return relativeSharedMeasurements(a) < relativeSharedMeasurements(b);
123 }
124 return state.track_chi2[a] < state.track_chi2[b];
125 };
126
127 for (std::size_t i = 0; i < maximum_iterations_; ++i) {
128 // Lazy out if there is nothing to filter on.
129 if (state.selected_tracks.empty()) {
130 ldmx_log(trace) << "No tracks left - exit loop";
131 break;
132 }
133
134 // Find the maximum amount of shared measurements per track to decide if we
135 // are done or not.
136 auto maximumSharedMeasurements = *std::max_element(
137 state.selected_tracks.begin(), state.selected_tracks.end(),
138 sharedMeasurementsComperator);
139 // ldmx_log(debug) <<
140 // "maximum shared measurements "
141 // << state.sharedMeasurementsPerTrack[maximumSharedMeasurements];
142 if (state.shared_measurements_per_track[maximumSharedMeasurements] <
144 break;
145 }
146
147 // Find the "worst" track by comparing them to each other
148 auto badTrack =
149 *std::max_element(state.selected_tracks.begin(),
150 state.selected_tracks.end(), trackComperator);
151 ldmx_log(trace) << "Remove track " << badTrack << ", nMeas = "
152 << state.measurements_per_track[badTrack].size()
153 << ", nShared = "
154 << state.shared_measurements_per_track[badTrack]
155 << ", chi2 =" << state.track_chi2[badTrack];
156 removeTrack(state, badTrack);
157 }
158}
159
160// Processor Functions
161
163
165 framework::config::Parameters& parameters) {
166 out_trk_collection_ = parameters.getParameter<std::string>(
167 "out_trk_collection", "TaggerTracksClean");
168
169 track_collection_ =
170 parameters.getParameter<std::string>("trackCollection", "TaggerTracks");
171
172 meas_collection_ = parameters.getParameter<std::string>("measCollection",
173 "DigiTaggerSimHits");
174 input_pass_name_ =
175 parameters.getParameter<std::string>("input_pass_name", "");
176 n_meas_min_ = parameters.getParameter<int>("nMeasurementsMin", 5);
177 maximum_shared_hits_ = parameters.getParameter<int>("maximumSharedHits", 1);
178}
179
182 std::vector<ldmx::Track> out_tracks;
183
184 auto tg{geometry()};
185
186 if (!event.exists(track_collection_, input_pass_name_)) {
187 ldmx_log(debug) << "Track collection not found, exiting";
188 return;
189 }
190 auto tracks{
191 event.getCollection<ldmx::Track>(track_collection_, input_pass_name_)};
192
193 if (!event.exists(meas_collection_, input_pass_name_)) {
194 ldmx_log(debug) << "Measurement collection not found, exiting";
195 return;
196 }
197 auto measurements{event.getCollection<ldmx::Measurement>(meas_collection_,
198 input_pass_name_)};
199
200 computeInitialState(tracks, measurements, state, tg,
201 tracking::sim::utils::sourceLinkHash,
202 tracking::sim::utils::sourceLinkEquality);
203 resolve(state);
204
205 for (auto iTrack : state.selected_tracks) {
206 auto clean_trk = tracks[state.track_tips.at(iTrack)];
207 if ((clean_trk.getNhits() > n_meas_min_) &&
208 (std::abs(1. / clean_trk.getQoP()) > 0.05)) {
209 out_tracks.push_back(clean_trk);
210 }
211 }
212
213 event.add(out_trk_collection_, out_tracks);
214
215 // for (auto iTrack : initial_state.selectedTracks) {
216 // std::cout << event.getEventNumber() << " " << iTrack << " " <<
217 // initial_state.trackChi2[iTrack] << " " <<
218 // initial_state.measurementsPerTrack[iTrack].size() << std::endl;
219 // }
220
221 ldmx_log(info) << " Resolved to " << state.selected_tracks.size()
222 << " tracks from "
223 << " " << tracks.size();
224}
225
226} // namespace reco
227} // namespace tracking
228
229DECLARE_PRODUCER_NS(tracking::reco, GreedyAmbiguitySolver)
#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: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
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
GreedyAmbiguitySolver(const std::string &name, framework::Process &process)
Constructor.
std::size_t n_meas_min_
Minimum number of measurement to form a track.
void removeTrack(State &state, std::size_t iTrack) const
void configure(framework::config::Parameters &parameters) override
Configure the processor using the given user specified parameters.
void computeInitialState(std::vector< ldmx::Track > tracks, std::vector< ldmx::Measurement > measurements, State &state, geometry_t &tg, source_link_hash_t &&sourceLinkHash, source_link_equality_t &&sourceLinkEquality) const
void resolve(State &state)
Updates the state iteratively by evicting one track after the other until the final state conditions ...
void onNewRun(const ldmx::RunHeader &rh) override
onNewRun is the first function called for each processor after the conditions are fully configured an...
void produce(framework::Event &event) override
Process the event and put new data products into it.
std::uint32_t maximum_iterations_
Maximum number of iterations.
std::uint32_t maximum_shared_hits_
Maximum amount of shared hits per track.
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...