Belle II Software development
TrackCombiner Class Referenceabstract

Combines two sets of tracks to one final set by merging tracks that have large overlaps. More...

#include <TrackCombiner.h>

Inheritance diagram for TrackCombiner:
Findlet< const TrackingUtilities::CDCTrack, const TrackingUtilities::CDCTrack, TrackingUtilities::CDCTrack > CompositeProcessingSignalListener ProcessingSignalListener

Public Types

using IOTypes
 Types that should be served to apply on invocation.
 
using IOTypes
 Types that should be served to apply on invocation.
 
using IOVectors
 Vector types that should be served to apply on invocation.
 
using IOVectors
 Vector types that should be served to apply on invocation.
 

Public Member Functions

 TrackCombiner ()
 Default constructor.
 
std::string getDescription () final
 Short description of the findlet.
 
void exposeParameters (ModuleParamList *moduleParamList, const std::string &prefix) final
 Expose the parameters to a module.
 
void apply (const std::vector< TrackingUtilities::CDCTrack > &inputTracks, const std::vector< TrackingUtilities::CDCTrack > &secondInputTracks, std::vector< TrackingUtilities::CDCTrack > &tracks) final
 Main algorithm.
 
virtual void apply (ToVector< AIOTypes > &... ioVectors)=0
 Main function executing the algorithm.
 
void initialize () override
 Receive and dispatch signal before the start of the event processing.
 
void beginRun () override
 Receive and dispatch signal for the beginning of a new run.
 
void beginEvent () override
 Receive and dispatch signal for the start of a new event.
 
void endRun () override
 Receive and dispatch signal for the end of the run.
 
void terminate () override
 Receive and dispatch Signal for termination of the event processing.
 

Protected Types

using ToVector
 Short hand for ToRangeImpl.
 
using ToVector
 Short hand for ToRangeImpl.
 

Protected Member Functions

void addProcessingSignalListener (ProcessingSignalListener *psl)
 Register a processing signal listener to be notified.
 
int getNProcessingSignalListener ()
 Get the number of currently registered listeners.
 

Private Types

using Super
 Type of the base class.
 

Private Attributes

bool m_param_identifyCommonSegments = false
 Parameter : Activate the identification of common segments.
 
TrackingUtilities::MultipassCellularPathFinder< const TrackingUtilities::CDCSegment3Dm_cellularPathFinder
 Instance of the cellular automaton path finder.
 
std::vector< ProcessingSignalListener * > m_subordinaryProcessingSignalListeners
 References to subordinary signal processing listener contained in this findlet.
 
bool m_initialized
 Flag to keep track whether initialization happened before.
 
bool m_terminated
 Flag to keep track whether termination happened before.
 
std::string m_initializedAs
 Name of the type during initialisation.
 

Detailed Description

Combines two sets of tracks to one final set by merging tracks that have large overlaps.

Definition at line 31 of file TrackCombiner.h.

Member Typedef Documentation

◆ IOTypes [1/2]

using IOTypes
inherited

Types that should be served to apply on invocation.

Definition at line 30 of file Findlet.h.

◆ IOTypes [2/2]

using IOTypes
inherited

Types that should be served to apply on invocation.

Definition at line 30 of file Findlet.h.

◆ IOVectors [1/2]

using IOVectors
inherited

Vector types that should be served to apply on invocation.

Definition at line 53 of file Findlet.h.

◆ IOVectors [2/2]

using IOVectors
inherited

Vector types that should be served to apply on invocation.

Definition at line 53 of file Findlet.h.

◆ Super

using Super
private
Initial value:

Type of the base class.

Definition at line 36 of file TrackCombiner.h.

◆ ToVector [1/2]

using ToVector
protectedinherited

Short hand for ToRangeImpl.

Definition at line 49 of file Findlet.h.

◆ ToVector [2/2]

using ToVector
protectedinherited

Short hand for ToRangeImpl.

Definition at line 49 of file Findlet.h.

Member Function Documentation

◆ addProcessingSignalListener()

void addProcessingSignalListener ( ProcessingSignalListener * psl)
protectedinherited

Register a processing signal listener to be notified.

Definition at line 53 of file CompositeProcessingSignalListener.cc.

◆ apply()

void apply ( const std::vector< TrackingUtilities::CDCTrack > & inputTracks,
const std::vector< TrackingUtilities::CDCTrack > & secondInputTracks,
std::vector< TrackingUtilities::CDCTrack > & tracks )
final

Main algorithm.

Definition at line 99 of file TrackCombiner.cc.

102{
103 using InTracks = std::array<const CDCTrack*, 2>;
104
105 // Constructing map of back links
106 std::map<const CDCWireHit*, InTracks> inTracksByWireHit;
107 for (const CDCTrack& track : inputTracks) {
108 for (const CDCRecoHit3D& recoHit3D : track) {
109 const CDCWireHit& wireHit = recoHit3D.getWireHit();
110 if (inTracksByWireHit.count(&wireHit) == 0) inTracksByWireHit[&wireHit] = {nullptr, nullptr};
111 inTracksByWireHit[&wireHit][0] = &track;
112 // Prepare hits for the cellular automaton
113 wireHit->unsetTemporaryFlags();
114 wireHit->unsetMaskedFlag();
115 }
116 }
117
118 for (const CDCTrack& track : secondInputTracks) {
119 for (const CDCRecoHit3D& recoHit3D : track) {
120 const CDCWireHit& wireHit = recoHit3D.getWireHit();
121 if (inTracksByWireHit.count(&wireHit) == 0) inTracksByWireHit[&wireHit] = {nullptr, nullptr};
122 inTracksByWireHit[&wireHit][1] = &track;
123 // Prepare hits for the cellular automaton
124 wireHit->unsetTemporaryFlags();
125 wireHit->unsetMaskedFlag();
126 }
127 }
128
129 // Rank tracks by number of superlayers touched first and number of hits second
130 std::vector<std::pair<std::pair<int, size_t>, const CDCTrack*> > rankedTracks;
131 for (const CDCTrack& track : inputTracks) {
132 std::array<int, ISuperLayerUtil::c_N> nHitsBySLayer = getNHitsByISuperLayer(track);
133 int nSL = std::count_if(nHitsBySLayer.begin(), nHitsBySLayer.end(), Id() > 0);
134 rankedTracks.push_back({{nSL, track.size()}, &track});
135 }
136 for (const CDCTrack& track : secondInputTracks) {
137 std::array<int, ISuperLayerUtil::c_N> nHitsBySLayer = getNHitsByISuperLayer(track);
138 int nSL = std::count_if(nHitsBySLayer.begin(), nHitsBySLayer.end(), Id() > 0);
139 rankedTracks.push_back({{nSL, track.size()}, &track});
140 }
141 std::sort(rankedTracks.begin(), rankedTracks.end(), GreaterOf<First>());
142
143 // Memory for the split segments
144 std::deque<CDCSegment3D> segments;
145
146 // Memory for the relations between tracks to be followed on linking
147 std::vector<WeightedRelation<const CDCSegment3D>> segmentRelations;
148
149 // Also keep a record to which of the tracks the segment
150 std::map<const CDCSegment3D*, InTracks> inTracksBySegment;
151
152 // Split tracks into segments - break segment such that there will be matching pieces with the other tracks
153 for (const std::pair<std::pair<int, size_t>, const CDCTrack*>& rankedTrack : rankedTracks) {
154 // const std::pair<ISuperLayer, size_t> rank = rankedTrack.first;
155 const CDCTrack* track = rankedTrack.second;
156 std::vector<std::pair<InTracks, CDCSegment3D> > segmentsInTrack;
157
158 // Split track into segments
159 CDCSegment3D* currentSegment = nullptr;
160 ISuperLayer lastISuperLayer = -1;
161 InTracks lastTracksForHit{{nullptr, nullptr}};
162 for (const CDCRecoHit3D& recoHit3D : *track) {
163 ISuperLayer iSuperLayer = recoHit3D.getISuperLayer();
164 std::array<const CDCTrack*, 2> tracksForWireHit = inTracksByWireHit[&recoHit3D.getWireHit()];
165 if (not currentSegment or iSuperLayer != lastISuperLayer or tracksForWireHit != lastTracksForHit) {
166 // Make new segments
167 segmentsInTrack.push_back({tracksForWireHit, CDCSegment3D()});
168 currentSegment = &segmentsInTrack.back().second;
169 currentSegment->setTrajectory3D(track->getStartTrajectory3D());
170 }
171 currentSegment->push_back(recoHit3D);
172 lastISuperLayer = iSuperLayer;
173 lastTracksForHit = tracksForWireHit;
174 }
175
176 // Merge small segments
177 auto absorbsSegment = [](std::pair<InTracks, CDCSegment3D>& segment1,
178 std::pair<InTracks, CDCSegment3D>& segment2) {
179
180 if (segment1.second.getISuperLayer() != segment2.second.getISuperLayer()) return false;
181 if (segment1.second.size() < 3) {
182 segment1.first = segment2.first;
183 }
184 // Absorb segment1 into segment2
185 if (segment1.second.size() < 3 or segment2.second.size() < 3 or
186 segment1.first == segment2.first) {
187 segment1.second.insert(segment1.second.end(),
188 segment2.second.begin(),
189 segment2.second.end());
190 return true;
191 }
192 return false;
193 };
194 auto itSegmentToDrop = std::unique(segmentsInTrack.begin(), segmentsInTrack.end(), absorbsSegment);
195 segmentsInTrack.erase(itSegmentToDrop, segmentsInTrack.end());
196
197 size_t nHits = 0;
198 for (std::pair<InTracks, CDCSegment3D>& segment : segmentsInTrack) {
199 nHits += segment.second.size();
200 }
201 B2ASSERT("Expected the number of hits to be the same", nHits == track->size());
202
203 // Push segments to the common pool
204 const CDCSegment3D* lastSegment = nullptr;
205 for (std::pair<InTracks, CDCSegment3D>& segmentInTrack : segmentsInTrack) {
206 const InTracks& inTracks = segmentInTrack.first;
207 const CDCSegment3D& segment = segmentInTrack.second;
208 segment->setCellWeight(segment.size());
209 segments.push_back(std::move(segment));
210 inTracksBySegment[&segments.back()] = inTracks;
211 if (lastSegment != nullptr) {
212 segmentRelations.push_back({lastSegment, 0, &segments.back()});
213 }
214 lastSegment = &segments.back();
215 }
216 }
217
218 // Sort the relations for the lookup
219 std::sort(segmentRelations.begin(), segmentRelations.end());
220
221 // Identify common segments, also checking whether they have the same orientation
223 std::vector<std::pair<const CDCSegment3D*, const CDCSegment3D*>> segmentContainmentRelation;
224 for (auto itSegment1 = segments.begin(); itSegment1 != segments.end(); ++itSegment1) {
225 const CDCSegment3D& segment1 = *itSegment1;
226 std::vector<CDCRLWireHit> rlWireHits1 = getRLWireHitSegment(segment1);
227 ISuperLayer iSL1 = segment1.getISuperLayer();
228 InTracks inTracks1 = inTracksBySegment[&segment1];
229 for (auto itSegment2 = itSegment1 + 1; itSegment2 != segments.end(); ++itSegment2) {
230 const CDCSegment3D& segment2 = *itSegment2;
231
232 // Should not happen - here for safety reasons
233 if (&segment1 == &segment2) continue;
234
235 ISuperLayer iSL2 = segment2.getISuperLayer();
236 if (iSL1 != iSL2) continue;
237
238 InTracks inTracks2 = inTracksBySegment[&segment2];
239 if (inTracks1 != inTracks2) continue;
240
241 // Now answering the question if segment 1 is contained in segment 2
242 std::vector<CDCRLWireHit> rlWireHits2 = getRLWireHitSegment(segment2);
243 std::vector<std::pair<std::pair<int, int>, CDCRLWireHit>> commonRLWireHits =
244 getCommonRLWireHits(rlWireHits1, rlWireHits2);
245
246 // Check for containment, requiring that the majority of the wire hits of one is in two
247 // However also require that the two is not too much larger compared to the first one
248 bool contains = commonRLWireHits.size() > 2 and
249 commonRLWireHits.size() > rlWireHits1.size() * 0.8 and
250 commonRLWireHits.size() > rlWireHits2.size() * 0.8;
251 if (not contains) continue;
252
253 // Now finally check whether both segments point in the same direction
254 double n = commonRLWireHits.size();
255 double prod11 = 0;
256 double prod12 = 0;
257 double prod22 = 0;
258 double sum1 = 0;
259 double sum2 = 0;
260 for (const auto& commonRLWireHit : commonRLWireHits) {
261 const std::pair<int, int>& indices = commonRLWireHit.first;
262 prod11 += indices.first * indices.first;
263 prod12 += indices.first * indices.second;
264 prod22 += indices.second * indices.second;
265
266 sum1 += indices.first;
267 sum2 += indices.second;
268 }
269 double var1 = (prod11 - sum1 * sum1 / n);
270 double var2 = (prod22 - sum2 * sum2 / n);
271 double cov12 = (prod12 - sum1 * sum2 / n);
272 double cor = cov12 / std::sqrt(var1 * var2);
273 if (not(cor > 0.75)) continue;
274
275 segmentContainmentRelation.push_back({&segment1, &segment2});
276 }
277 }
278
279 // Create additional edges
280 std::vector<WeightedRelation<const CDCSegment3D>> additionalSegmentRelations;
281 for (std::pair<const CDCSegment3D*, const CDCSegment3D*>& rel : segmentContainmentRelation) {
282 for (WeightedRelation<const CDCSegment3D> rel1 :
283 asRange(std::equal_range(segmentRelations.begin(), segmentRelations.end(), rel.first))) {
284 additionalSegmentRelations.push_back({rel.second, 0, rel1.getTo()});
285 }
286
287 for (WeightedRelation<const CDCSegment3D> rel2 : asRange(
288 std::equal_range(segmentRelations.begin(), segmentRelations.end(), rel.second))) {
289 additionalSegmentRelations.push_back({rel.first, 0, rel2.getFrom()});
290 }
291 }
292 segmentRelations.insert(segmentRelations.end(),
293 additionalSegmentRelations.begin(),
294 additionalSegmentRelations.end());
295 std::sort(segmentRelations.begin(), segmentRelations.end());
296 }
297
298 // Extract paths
299 // Obtain the segments as pointers
300 std::vector<const CDCSegment3D*> segmentPtrs = as_pointers<const CDCSegment3D>(segments);
301
302 // Memory for the track paths generated from the graph.
303 std::vector<Path<const CDCSegment3D>> segmentPaths;
304 m_cellularPathFinder.apply(segmentPtrs, segmentRelations, segmentPaths);
305
306 // Put the linked segments together
307 outputTracks.clear();
308 for (const std::vector<const CDCSegment3D*>& segmentPath : segmentPaths) {
309 // Reject single left over segments
310 if (segmentPath.size() < 2) continue;
311 outputTracks.push_back(condense(segmentPath));
312 }
313
314 // Simple approach
315 // Incorporate the second input tracks in to the first input tracks by looking for large overlaps
316 // Very simple approach use the first tracks and add the ones from the second tracks with no overlap to the first
317 // outputTracks.insert(outputTracks.end(), inputTracks.begin(), inputTracks.end());
318 // for (const CDCTrack& secondTrack : secondInputTracks) {
319 // std::map<const CDCTrack*, int> overlappingTracks;
320 // for (const CDCRecoHit3D& recoHit3D : secondTrack) {
321 // const CDCWireHit& wireHit = recoHit3D.getWireHit();
322 // inTracksByWireHit.equal_range(&recoHit3D.getWireHit());
323 // auto tracksForWireHit = asRange(inTracksByWireHit.equal_range(&wireHit));
324 // for (const std::pair<const CDCWireHit*, InTracks>& trackForWireHit : inTracksByWireHit) {
325 // const CDCTrack* track = trackForWireHit.second[0];
326 // if (not track) continue;
327 // overlappingTracks[track]++;
328 // }
329 // }
330 // if (overlappingTracks.size() == 0) {
331 // outputTracks.push_back(secondTrack);
332 // }
333 // }
334}
bool m_param_identifyCommonSegments
Parameter : Activate the identification of common segments.
TrackingUtilities::MultipassCellularPathFinder< const TrackingUtilities::CDCSegment3D > m_cellularPathFinder
Instance of the cellular automaton path finder.
void unsetMaskedFlag()
Resets the masked flag to false.
void unsetTemporaryFlags()
Resets the assigned, start and cycle marker flag.
CDC::ISuperLayer getISuperLayer() const
Returns the common super layer id of all stored tracking hits.
Definition CDCSegment.h:57
signed short ISuperLayer
The type of the layer and superlayer ids.
Definition ISuperLayer.h:24

◆ beginEvent()

void beginEvent ( )
overrideinherited

Receive and dispatch signal for the start of a new event.

Definition at line 36 of file CompositeProcessingSignalListener.cc.

32{
35 psl->beginEvent();
36 }
37}
void beginEvent() override
Receive and dispatch signal for the start of a new event.
virtual void beginEvent()
Receive signal for the start of a new event.

◆ beginRun()

void beginRun ( )
overrideinherited

Receive and dispatch signal for the beginning of a new run.

Definition at line 33 of file CompositeProcessingSignalListener.cc.

24{
27 psl->beginRun();
28 }
29}
void beginRun() override
Receive and dispatch signal for the beginning of a new run.
virtual void beginRun()
Receive signal for the beginning of a new run.

◆ endRun()

void endRun ( )
overrideinherited

Receive and dispatch signal for the end of the run.

Definition at line 39 of file CompositeProcessingSignalListener.cc.

40{
42 psl->endRun();
43 }
45}
void endRun() override
Receive and dispatch signal for the end of the run.
virtual void endRun()
Receive signal for the end of the run.

◆ exposeParameters()

void exposeParameters ( ModuleParamList * moduleParamList,
const std::string & prefix )
finalvirtual

Expose the parameters to a module.

Reimplemented from CompositeProcessingSignalListener.

Definition at line 90 of file TrackCombiner.cc.

92{
93 moduleParamList->addParameter(prefixed(prefix, "identifyCommonSegments"),
95 "Activate the identification of common segments",
97}
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.

◆ getDescription()

std::string getDescription ( )
finalvirtual

Short description of the findlet.

Reimplemented from Findlet< const TrackingUtilities::CDCTrack, const TrackingUtilities::CDCTrack, TrackingUtilities::CDCTrack >.

Definition at line 85 of file TrackCombiner.cc.

86{
87 return "Combines two sets of tracks to one final set by merging tracks that have large overlaps.";
88}

◆ getNProcessingSignalListener()

int getNProcessingSignalListener ( )
protectedinherited

Get the number of currently registered listeners.

Definition at line 56 of file CompositeProcessingSignalListener.cc.

61{
63}

◆ initialize()

void initialize ( )
overrideinherited

Receive and dispatch signal before the start of the event processing.

Definition at line 30 of file CompositeProcessingSignalListener.cc.

16{
19 psl->initialize();
20 }
21}
void initialize() override
Receive and dispatch signal before the start of the event processing.
virtual void initialize()
Receive signal before the start of the event processing.

◆ terminate()

void terminate ( )
overrideinherited

Receive and dispatch Signal for termination of the event processing.

Definition at line 42 of file CompositeProcessingSignalListener.cc.

48{
50 psl->terminate();
51 }
53}
void terminate() override
Receive and dispatch Signal for termination of the event processing.
virtual void terminate()
Receive Signal for termination of the event processing.

Member Data Documentation

◆ m_cellularPathFinder

Instance of the cellular automaton path finder.

Definition at line 61 of file TrackCombiner.h.

◆ m_initialized

bool m_initialized
privateinherited

Flag to keep track whether initialization happened before.

Definition at line 52 of file ProcessingSignalListener.h.

◆ m_initializedAs

std::string m_initializedAs
privateinherited

Name of the type during initialisation.

Definition at line 58 of file ProcessingSignalListener.h.

◆ m_param_identifyCommonSegments

bool m_param_identifyCommonSegments = false
private

Parameter : Activate the identification of common segments.

Definition at line 57 of file TrackCombiner.h.

◆ m_subordinaryProcessingSignalListeners

std::vector<ProcessingSignalListener*> m_subordinaryProcessingSignalListeners
privateinherited

References to subordinary signal processing listener contained in this findlet.

Definition at line 60 of file CompositeProcessingSignalListener.h.

◆ m_terminated

bool m_terminated
privateinherited

Flag to keep track whether termination happened before.

Definition at line 55 of file ProcessingSignalListener.h.


The documentation for this class was generated from the following files: