Bug Summary

File:libraries/TRACKING/DTrackCandidate_factory_CDC.cc
Location:line 4820, column 61
Description:Access to field 'dSuperLayer' results in a dereference of a null pointer (loaded from variable 'locLastAxialSuperLayerSeed')

Annotated Source Code

1// $Id$
2//
3// File: DTrackCandidate_factory_CDC.cc
4// Created: Thu Sep 6 14:47:48 EDT 2007
5// Creator: davidl (on Darwin Amelia.local 8.10.1 i386)
6//
7
8#include "DTrackCandidate_factory_CDC.h"
9#include <cmath>
10#include <JANA/JCalibration.h>
11
12#define BeamRMS0.5 0.5
13#define EPS1e-3 1e-3
14
15#define TWO(c)(0x1u << (c)) (0x1u << (c))
16#define MASK(c)((unsigned int)(-1)) / ((0x1u << ((0x1u << (c))))
+ 1u)
((unsigned int)(-1)) / (TWO(TWO(c))(0x1u << ((0x1u << (c)))) + 1u)
17#define COUNT(x,c)((x) & ((unsigned int)(-1)) / ((0x1u << ((0x1u <<
(c)))) + 1u)) + (((x) >> ((0x1u << (c)))) & (
(unsigned int)(-1)) / ((0x1u << ((0x1u << (c)))) +
1u))
((x) & MASK(c)((unsigned int)(-1)) / ((0x1u << ((0x1u << (c))))
+ 1u)
) + (((x) >> (TWO(c)(0x1u << (c)))) & MASK(c)((unsigned int)(-1)) / ((0x1u << ((0x1u << (c))))
+ 1u)
)
18
19#ifndef M_TWO_PI6.28318530717958647692
20#define M_TWO_PI6.28318530717958647692 6.28318530717958647692
21#endif
22
23using namespace std;
24
25inline int bitcount(unsigned int n)
26{
27 n = COUNT(n, 0)((n) & ((unsigned int)(-1)) / ((0x1u << ((0x1u <<
(0)))) + 1u)) + (((n) >> ((0x1u << (0)))) & (
(unsigned int)(-1)) / ((0x1u << ((0x1u << (0)))) +
1u))
;
28 n = COUNT(n, 1)((n) & ((unsigned int)(-1)) / ((0x1u << ((0x1u <<
(1)))) + 1u)) + (((n) >> ((0x1u << (1)))) & (
(unsigned int)(-1)) / ((0x1u << ((0x1u << (1)))) +
1u))
;
29 n = COUNT(n, 2)((n) & ((unsigned int)(-1)) / ((0x1u << ((0x1u <<
(2)))) + 1u)) + (((n) >> ((0x1u << (2)))) & (
(unsigned int)(-1)) / ((0x1u << ((0x1u << (2)))) +
1u))
;
30 n = COUNT(n, 3)((n) & ((unsigned int)(-1)) / ((0x1u << ((0x1u <<
(3)))) + 1u)) + (((n) >> ((0x1u << (3)))) & (
(unsigned int)(-1)) / ((0x1u << ((0x1u << (3)))) +
1u))
;
31 n = COUNT(n, 4)((n) & ((unsigned int)(-1)) / ((0x1u << ((0x1u <<
(4)))) + 1u)) + (((n) >> ((0x1u << (4)))) & (
(unsigned int)(-1)) / ((0x1u << ((0x1u << (4)))) +
1u))
;
32 //n = COUNT(n, 5); for 64-bit integers
33 return n;
34}
35
36inline bool CDCSortByRdecreasing(const DTrackCandidate_factory_CDC::DCDCTrkHit* hit1, const DTrackCandidate_factory_CDC::DCDCTrkHit* hit2)
37{
38 // use the ring number to sort by R(decreasing) and then straw(increasing)
39 if(hit1->hit->wire->ring == hit2->hit->wire->ring)
40 return hit1->hit->wire->straw < hit2->hit->wire->straw;
41 return hit1->hit->wire->ring > hit2->hit->wire->ring;
42}
43
44inline bool CDCSortByChiSqPerNDFDecreasing(const DTrackCandidate_factory_CDC::DCDCTrackCircle* locTrackCircle1, const DTrackCandidate_factory_CDC::DCDCTrackCircle* locTrackCircle2)
45{
46 // largest weighted fit chisq/ndf is first
47 return (locTrackCircle1->dWeightedChiSqPerDF > locTrackCircle2->dWeightedChiSqPerDF);
48}
49
50inline bool CDCSortByStereoChiSqPerNDFIncreasing(const DTrackCandidate_factory_CDC::DCDCTrackCircle* locTrackCircle1, const DTrackCandidate_factory_CDC::DCDCTrackCircle* locTrackCircle2)
51{
52 // smallest weighted theta/z chisq/ndf is first
53 return (locTrackCircle1->dWeightedChiSqPerDF_Stereo < locTrackCircle2->dWeightedChiSqPerDF_Stereo);
54}
55
56inline bool CDCSort_Intersections(const DTrackCandidate_factory_CDC::intersection_t& locIntersection1, const DTrackCandidate_factory_CDC::intersection_t& locIntersection2)
57{
58 return (locIntersection1.perp2 < locIntersection2.perp2);
59}
60
61inline bool CDCSort_DeltaPhis(const pair<DTrackCandidate_factory_CDC::DCDCTrkHit*, double>& locDeltaPhiPair1, const pair<DTrackCandidate_factory_CDC::DCDCTrkHit*, double>& locDeltaPhiPair2)
62{
63 //smallest delta-phi is first
64 return (locDeltaPhiPair1.second < locDeltaPhiPair2.second);
65}
66
67DTrackCandidate_factory_CDC::~DTrackCandidate_factory_CDC(){
68
69}
70
71
72//------------------
73// init
74//------------------
75jerror_t DTrackCandidate_factory_CDC::init(void)
76{
77 DEBUG_LEVEL = 0;
78 MAX_DCDCTrkHitPoolSize = 200;
79 MAX_DCDCSuperLayerSeedPoolSize = 50;
80 MAX_HelicalFitPoolSize = 100;
81 MAX_DCDCTrackCirclePoolSize = 100;
82
83 MAX_ALLOWED_CDC_HITS = 10000;
84 MAX_ALLOWED_TRACK_CIRCLES = 5000;
85 MAX_HIT_DIST = 4.0; // cm //each straw is 5/8in (1.5875 cm) in diameter
86 MAX_HIT_DIST2 = MAX_HIT_DIST*MAX_HIT_DIST;
87
88 //when linking DCDCRingSeed's together to form DCDCSuperLayerSeed's, allow skipping of rings
89 //for example, say there are hits in ring 1 and ring 3, but none in ring 2 because the particle didn't deposit enough energy.
90 //setting MAX_NUM_RINGSEED_RINGS_SKIPABLE >= 1 will recover these cases
91 MAX_NUM_RINGSEED_RINGS_SKIPABLE = 1;
92
93 MIN_SEED_HITS = 2;
94
95 // to be labeled as a potential/definite spiral turn (in/out-wards), the following conditions need to be met (where appropriate):
96 MIN_STRAWS_POTENTIAL_SPIRAL_TURN = 4; //minimum number of straws in a DCDCRingSeed necessary to be labeled as a potential spiral turn (in/out-wards)
97 MIN_STRAWS_DEFINITE_SPIRAL_TURN = 6; //minimum number of straws in a DCDCRingSeed necessary to be labeled as a definite spiral turn (in/out-wards)
98 MIN_STRAWS_ADJACENT_TO_SPIRAL_TURN = 3; // in some cases, this is the minimum number of straws in a DCDCRingSeed that is adjacent to the spiral turn (in/out-wards)
99 // if a spiral turn occurs between rings or outside the CDC, the below is the max # of straws that can be between two DCDCRingSeed's in the adjacent ring
100 // the two DCDCRingSeed's would be in different super layer seeds
101 MAX_STRAWS_BETWEEN_LINK_SPIRAL_TURN = 6;
102
103 //within a super layer, if the number of seeds in a region of width SEED_DENSITY_BIN_STRAW_WIDTH is greater than MAX_SEEDS_IN_STRAW_BIN, reject all seeds passing through this region
104 //note that since the # of straws increases with ring #, the region width is technically computed as a phi region:
105 //from phi of straw 'N' in the first ring of a given super layer, to the phi of straw 'N + DENSITY_BIN_STRAW_WIDTH - 1'
106 SEED_DENSITY_BIN_STRAW_WIDTH = 8;
107 MAX_SEEDS_IN_STRAW_BIN = 15;
108
109 //when true, will allow linking of super layer seeds to skip a super layer (in case there is a dead HV board there)
110 //note that this feature is not fully tested!!
111 ENABLE_DEAD_HV_BOARD_LINKING = false;
112
113 //don't allow new track seeds to start after this super layer
114 //track seeds could start late if track is a decay product, or HV board is dead
115 //this is to prevent tracks forming that are complete garbage (e.g. a spiral craziness, knockout electrons re-entering the CDC from the BCAL, etc.)
116 MAX_SUPERLAYER_NEW_TRACK = 4;
117
118 // the maximum # of hits allowed to be shared between the axial super layer seeds of DCDCTrackCircle's
119 // if > than this amount, the track with the larger circle-fit weighted-chisq/ndf will be rejected
120 MAX_COMMON_HIT_FRACTION = 0.49; //reject if exactly half
121
122 MAX_DRIFT_TIME = 1000.0; // ns
123 MAX_SEED_TIME_DIFF = 1000.0; // ns
124
125 // used for identifying arms of a spiral: can be true if the centers of the fit circles are close together (relative to their difference from the origin)
126 MIN_CIRCLE_ASYMMETRY = 0.10;
127
128 // when calculating the final theta/z, include at least this many stereo hits for the calculation
129 // don't want to include stereo hits whose projections onto the track circle are too far away
130 MIN_PRUNED_STEREO_HITS = 4;
131
132 // when searching for unused axial hits to add to the track, require that the hit be within this #-degrees in phi to the circle fit
133 MAX_UNUSED_HIT_LINK_ANGLE = 10.0; //degrees
134
135 TARGET_Z = 65.0;
136 VERTEX_Z_MIN = -100.0;
137 VERTEX_Z_MAX = 200.0;
138
139 cdchits_by_superlayer.resize(7);
140 dSuperLayerSeeds.resize(7);
141 for(unsigned int loc_i = 0; loc_i < 7; ++loc_i)
142 superlayer_boundaries.push_back(4*(1 + loc_i));
143
144 dNumStrawsPerRing.resize(28);
145
146 dNumSeedDensityPhiBins = 360;
147
148 return NOERROR;
149}
150
151//------------------
152// brun
153//------------------
154jerror_t DTrackCandidate_factory_CDC::brun(JEventLoop *locEventLoop, int32_t runnumber)
155{
156 gPARMS->SetDefaultParameter("TRKFIND:DEBUG_LEVEL", DEBUG_LEVEL);
157 gPARMS->SetDefaultParameter("TRKFIND:MAX_ALLOWED_CDC_HITS", MAX_ALLOWED_CDC_HITS);
158 gPARMS->SetDefaultParameter("TRKFIND:MAX_ALLOWED_TRACK_CIRCLES", MAX_ALLOWED_TRACK_CIRCLES);
159 gPARMS->SetDefaultParameter("TRKFIND:MAX_HIT_DIST", MAX_HIT_DIST);
160 gPARMS->SetDefaultParameter("TRKFIND:MAX_NUM_RINGSEED_RINGS_SKIPABLE", MAX_NUM_RINGSEED_RINGS_SKIPABLE);
161 gPARMS->SetDefaultParameter("TRKFIND:MIN_SEED_HITS", MIN_SEED_HITS);
162 gPARMS->SetDefaultParameter("TRKFIND:MIN_STRAWS_POTENTIAL_SPIRAL_TURN", MIN_STRAWS_POTENTIAL_SPIRAL_TURN);
163 gPARMS->SetDefaultParameter("TRKFIND:MIN_STRAWS_DEFINITE_SPIRAL_TURN", MIN_STRAWS_DEFINITE_SPIRAL_TURN);
164 gPARMS->SetDefaultParameter("TRKFIND:MIN_STRAWS_ADJACENT_TO_SPIRAL_TURN", MIN_STRAWS_ADJACENT_TO_SPIRAL_TURN);
165 gPARMS->SetDefaultParameter("TRKFIND:MAX_STRAWS_BETWEEN_LINK_SPIRAL_TURN", MAX_STRAWS_BETWEEN_LINK_SPIRAL_TURN);
166 gPARMS->SetDefaultParameter("TRKFIND:SEED_DENSITY_BIN_STRAW_WIDTH", SEED_DENSITY_BIN_STRAW_WIDTH);
167 gPARMS->SetDefaultParameter("TRKFIND:MAX_SEEDS_IN_STRAW_BIN", MAX_SEEDS_IN_STRAW_BIN);
168 gPARMS->SetDefaultParameter("TRKFIND:ENABLE_DEAD_HV_BOARD_LINKING", ENABLE_DEAD_HV_BOARD_LINKING);
169 gPARMS->SetDefaultParameter("TRKFIND:MAX_SUPERLAYER_NEW_TRACK", MAX_SUPERLAYER_NEW_TRACK);
170 gPARMS->SetDefaultParameter("TRKFIND:MAX_COMMON_HIT_FRACTION", MAX_COMMON_HIT_FRACTION);
171 gPARMS->SetDefaultParameter("TRKFIND:MIN_CIRCLE_ASYMMETRY", MIN_CIRCLE_ASYMMETRY);
172 gPARMS->SetDefaultParameter("TRKFIND:MAX_DRIFT_TIME", MAX_DRIFT_TIME);
173 gPARMS->SetDefaultParameter("TRKFIND:MAX_SEED_TIME_DIFF", MAX_SEED_TIME_DIFF);
174 gPARMS->SetDefaultParameter("TRKFIND:MIN_PRUNED_STEREO_HITS", MIN_PRUNED_STEREO_HITS);
175 gPARMS->SetDefaultParameter("TRKFIND:MAX_UNUSED_HIT_LINK_ANGLE", MAX_UNUSED_HIT_LINK_ANGLE);
176 gPARMS->SetDefaultParameter("TRKFIND:VERTEX_Z_MIN", VERTEX_Z_MIN);
177 gPARMS->SetDefaultParameter("TRKFIND:VERTEX_Z_MAX", VERTEX_Z_MAX);
178
179 MAX_HIT_DIST2 = MAX_HIT_DIST*MAX_HIT_DIST;
180
181 DApplication* locApplication = dynamic_cast<DApplication*>(locEventLoop->GetJApplication());
182 dMagneticField = locApplication->GetBfield(runnumber);
183 dFactorForSenseOfRotation=(dMagneticField->GetBz(0.,0.,65.)>0.)?-1.:1.;
184
185 const DGeometry *locGeometry = locApplication->GetDGeometry(runnumber);
186 JCalibration *jcalib = locApplication->GetJCalibration(runnumber);
187 map<string, double> targetparms;
188 if (jcalib->Get("TARGET/target_parms",targetparms)==false){
189 TARGET_Z = targetparms["TARGET_Z_POSITION"];
190 }
191 else{
192 locGeometry->GetTargetZ(TARGET_Z);
193 }
194
195 // Get the CDC wire table from the XML
196 vector<vector<DCDCWire*> > locCDCWires;
197 locGeometry->GetCDCWires(locCDCWires);
198 for(size_t loc_i = 0; loc_i < locCDCWires.size(); ++loc_i)
199 dNumStrawsPerRing[loc_i] = locCDCWires[loc_i].size();
200
201 // Clean up after using wire map
202 for (size_t i=0;i<locCDCWires.size();i++){
203 for (size_t j=0;j<locCDCWires[i].size();j++){
204 delete locCDCWires[i][j];
205 }
206 }
207
208 return NOERROR;
209}
210
211//------------------
212// evnt
213//------------------
214jerror_t DTrackCandidate_factory_CDC::evnt(JEventLoop *locEventLoop, uint64_t eventnumber)
215{
216 // Reset
217 dRejectedPhiRegions.clear();
218
219 // Reset in case didn't clear before exiting event evaluation on last event.
220 Reset_Pools();
221
222 // Get CDC hits
223 if(Get_CDCHits(locEventLoop) != NOERROR)
224 {
225 Reset_Pools();
226 return RESOURCE_UNAVAILABLE;
227 }
228
229 // Build Super Layer Seeds
230 for(unsigned int loc_i = 0; loc_i < 7; ++loc_i)
231 {
232 if(DEBUG_LEVEL > 3)
233 cout << "Find Seeds, Super Layer = " << loc_i + 1 << endl;
234 Find_SuperLayerSeeds(cdchits_by_superlayer[loc_i], loc_i + 1);
235 Reject_SuperLayerSeeds_HighSeedDensity(loc_i + 1);
236 }
237 // Search for Spiral Links in and between super layer seeds
238 Set_SpiralLinkParams();
239 if(DEBUG_LEVEL > 5)
240 {
241 cout << "init super layers" << endl;
242 Print_SuperLayerSeeds();
243 }
244
245 // Build DCDCTrackCircle objects (each corresponds to (at most) one track):
246 deque<DCDCTrackCircle*> locCDCTrackCircles;
247 bool locStatusFlag = Build_TrackCircles(locCDCTrackCircles);
248 if(!locStatusFlag)
249 {
250 //SHOULD SET JEVENT STATUS BIT HERE!!!
251 Reset_Pools();
252 return OBJECT_NOT_AVAILABLE;
253 }
254 if(locCDCTrackCircles.empty())
255 {
256 Reset_Pools();
257 return NOERROR;
258 }
259 Handle_StereoAndFilter(locCDCTrackCircles, false); //false: not final pass: filter seeds, don't reject seeds with no stereo hits (will add unused below), etc.
260
261 // If the last super layer of a track is not 7, search for lone, unused hits on the next super layer and add them to the track
262 // Only add them if they are close enough to the track circle fit
263 Add_UnusedHits(locCDCTrackCircles);
264
265 // using axial on the track, redo the circle fit and re-calc theta-z
266 // This is for when extra hits are picked up by Add_UnusedHits, and for including midpoints between SL2/SL3 & SL5/SL6
267 //fit circles will reject fits if they aren't very good //false: fit all circles //true: add intersections between stereo layers
268 Fit_Circles(locCDCTrackCircles, false, true); //will reject fits if they aren't very good
269 if(DEBUG_LEVEL > 5)
270 {
271 cout << "final fit track circles" << endl;
272 Print_TrackCircles(locCDCTrackCircles);
273 }
274 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByChiSqPerNDFDecreasing); //sort by circle-fit weighted chisq/ndf (largest first)
275
276 Handle_StereoAndFilter(locCDCTrackCircles, true); //true: final pass: don't need to filter any more, get improved theta-z (although will reject if bad/no theta/z)
277 if(DEBUG_LEVEL > 5)
278 {
279 cout << "final track circles" << endl;
280 Print_TrackCircles(locCDCTrackCircles);
281 }
282
283 // Create track candidates (as long as p > 0!!)
284 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
285 Create_TrackCandidiate(locCDCTrackCircles[loc_i]);
286
287 // Reset memory before exiting event evaluation.
288 Reset_Pools();
289
290 return NOERROR;
291}
292
293//------------------
294// Reset_Pools
295//------------------
296void DTrackCandidate_factory_CDC::Reset_Pools(void)
297{
298 // delete pool contents if too large, preventing memory-leakage-like behavor.
299 if(dCDCTrkHitPool_All.size() > MAX_DCDCTrkHitPoolSize)
300 {
301 for(size_t loc_i = MAX_DCDCTrkHitPoolSize; loc_i < dCDCTrkHitPool_All.size(); ++loc_i)
302 delete dCDCTrkHitPool_All[loc_i];
303 dCDCTrkHitPool_All.resize(MAX_DCDCTrkHitPoolSize);
304 }
305 dCDCTrkHitPool_Available = dCDCTrkHitPool_All;
306
307 if(dCDCSuperLayerSeedPool_All.size() > MAX_DCDCSuperLayerSeedPoolSize)
308 {
309 for(size_t loc_i = MAX_DCDCSuperLayerSeedPoolSize; loc_i < dCDCSuperLayerSeedPool_All.size(); ++loc_i)
310 delete dCDCSuperLayerSeedPool_All[loc_i];
311 dCDCSuperLayerSeedPool_All.resize(MAX_DCDCSuperLayerSeedPoolSize);
312 }
313 dCDCSuperLayerSeedPool_Available = dCDCSuperLayerSeedPool_All;
314
315 if(dHelicalFitPool_All.size() > MAX_HelicalFitPoolSize)
316 {
317 for(unsigned int loc_i = MAX_HelicalFitPoolSize; loc_i < dHelicalFitPool_All.size(); ++loc_i)
318 delete dHelicalFitPool_All[loc_i];
319 dHelicalFitPool_All.resize(MAX_HelicalFitPoolSize);
320 }
321 dHelicalFitPool_Available = dHelicalFitPool_All;
322
323 if(dCDCTrackCirclePool_All.size() > MAX_DCDCTrackCirclePoolSize)
324 {
325 for(size_t loc_i = MAX_DCDCTrackCirclePoolSize; loc_i < dCDCTrackCirclePool_All.size(); ++loc_i)
326 delete dCDCTrackCirclePool_All[loc_i];
327 dCDCTrackCirclePool_All.resize(MAX_DCDCTrackCirclePoolSize);
328 }
329 dCDCTrackCirclePool_Available = dCDCTrackCirclePool_All;
330}
331
332DTrackCandidate_factory_CDC::DCDCTrkHit* DTrackCandidate_factory_CDC::Get_Resource_CDCTrkHit(void)
333{
334 DCDCTrkHit* locCDCTrkHit;
335 if(dCDCTrkHitPool_Available.empty())
336 {
337 locCDCTrkHit = new DCDCTrkHit;
338 dCDCTrkHitPool_All.push_back(locCDCTrkHit);
339 }
340 else
341 {
342 locCDCTrkHit = dCDCTrkHitPool_Available.back();
343 dCDCTrkHitPool_Available.pop_back();
344 }
345 locCDCTrkHit->Reset();
346 return locCDCTrkHit;
347}
348
349DTrackCandidate_factory_CDC::DCDCSuperLayerSeed* DTrackCandidate_factory_CDC::Get_Resource_CDCSuperLayerSeed(void)
350{
351 DCDCSuperLayerSeed* locCDCSuperLayerSeed;
352 if(dCDCSuperLayerSeedPool_Available.empty())
353 {
354 locCDCSuperLayerSeed = new DCDCSuperLayerSeed;
355 dCDCSuperLayerSeedPool_All.push_back(locCDCSuperLayerSeed);
356 }
357 else
358 {
359 locCDCSuperLayerSeed = dCDCSuperLayerSeedPool_Available.back();
360 dCDCSuperLayerSeedPool_Available.pop_back();
361 }
362 locCDCSuperLayerSeed->Reset();
363 return locCDCSuperLayerSeed;
364}
365
366DHelicalFit* DTrackCandidate_factory_CDC::Get_Resource_HelicalFit(void)
367{
368 DHelicalFit* locHelicalFit;
369 if(dHelicalFitPool_Available.empty())
370 {
371 locHelicalFit = new DHelicalFit;
372 dHelicalFitPool_All.push_back(locHelicalFit);
373 }
374 else
375 {
376 locHelicalFit = dHelicalFitPool_Available.back();
377 dHelicalFitPool_Available.pop_back();
378 }
379 locHelicalFit->Reset();
380 return locHelicalFit;
381}
382
383DTrackCandidate_factory_CDC::DCDCTrackCircle* DTrackCandidate_factory_CDC::Get_Resource_CDCTrackCircle(void)
384{
385 DCDCTrackCircle* locCDCTrackCircle;
386 if(dCDCTrackCirclePool_Available.empty())
387 {
388 locCDCTrackCircle = new DCDCTrackCircle;
389 dCDCTrackCirclePool_All.push_back(locCDCTrackCircle);
390 }
391 else
392 {
393 locCDCTrackCircle = dCDCTrackCirclePool_Available.back();
394 dCDCTrackCirclePool_Available.pop_back();
395 }
396 locCDCTrackCircle->Reset();
397 return locCDCTrackCircle;
398}
399
400//------------------
401// Get_CDCHits
402//------------------
403jerror_t DTrackCandidate_factory_CDC::Get_CDCHits(JEventLoop* loop)
404{
405 // Get the "raw" hits. These already have the wire associated with them.
406 vector<const DCDCTrackHit*> cdctrackhits;
407 loop->Get(cdctrackhits);
408 dNumCDCHits = cdctrackhits.size();
409
410 // If there are no hits, then bail now
411 if(cdctrackhits.empty())
412 return RESOURCE_UNAVAILABLE;
413
414 // If there are too many hits, bail with a warning message
415 if(cdctrackhits.size() > MAX_ALLOWED_CDC_HITS)
416 {
417 cout << "Too many hits in CDC (" <<cdctrackhits.size() << ", max = " << MAX_ALLOWED_CDC_HITS << ")! Track finding in CDC bypassed for event " << loop->GetJEvent().GetEventNumber() << endl;
418 cdctrackhits.clear();
419 return UNRECOVERABLE_ERROR;
420 }
421
422 // clear old hits
423 cdctrkhits.clear();
424 for(unsigned int i = 0; i < cdchits_by_superlayer.size(); i++)
425 cdchits_by_superlayer[i].clear();
426
427 // Create DCDCTrkHit objects out of these.
428 int oldwire = -1;
429 for(size_t i = 0; i< cdctrackhits.size(); ++i)
430 {
431 // Add to "master" list
432 // ONLY FIRST HIT OF A WIRE
433 int newwire = cdctrackhits[i]->wire->ring*1000 + cdctrackhits[i]->wire->straw;
434 if(newwire == oldwire)
435 continue;
436 oldwire = newwire;
437
438 if(DEBUG_LEVEL > 40)
439 cout << "adding ring, straw = " << cdctrackhits[i]->wire->ring << ", " << cdctrackhits[i]->wire->straw << endl;
440
441 // Add to "master" list
442 DCDCTrkHit* cdctrkhit = Get_Resource_CDCTrkHit();
443 cdctrkhit->index = i;
444 cdctrkhit->hit = cdctrackhits[i];
445 cdctrkhit->flags = NONE;
446 cdctrkhit->flags |= NOISE; // (see below)
447 cdctrkhits.push_back(cdctrkhit);
448
449 // Sort into list of hits by superlayer
450 for(size_t j = 0; j < superlayer_boundaries.size(); ++j)
451 {
452 if(cdctrkhit->hit->wire->ring <= int(superlayer_boundaries[j]))
453 {
454 cdchits_by_superlayer[j].push_back(cdctrkhit);
455 break;
456 }
457 }
458 }
459
460 // Sort the individual superlayer lists by decreasing values of R
461 for(size_t i = 0; i < cdchits_by_superlayer.size(); ++i)
462 sort(cdchits_by_superlayer[i].begin(), cdchits_by_superlayer[i].end(), CDCSortByRdecreasing);
463
464 // Filter out noise hits. All hits are initially flagged as "noise".
465 // Hits with a neighbor within MAX_HIT_DIST have their noise flags cleared.
466 // Also flag hits as out-of-time if their drift time is too large
467 for(size_t i = 0; i < cdctrkhits.size(); ++i)
468 {
469 DCDCTrkHit *trkhit1 = cdctrkhits[i];
470 if(trkhit1->hit->tdrift > MAX_DRIFT_TIME)
471 trkhit1->flags |= OUT_OF_TIME;
472 if(!(trkhit1->flags & NOISE))
473 continue; // this hit already not marked for noise
474 for(size_t j = 0; j < cdctrkhits.size(); ++j)
475 {
476 if(j == i)
477 continue;
478 double d2 = trkhit1->Dist2(cdctrkhits[j]);
479 if(d2 > 9.0*MAX_HIT_DIST2)
480 continue;
481 trkhit1->flags &= ~NOISE;
482 cdctrkhits[j]->flags &= ~NOISE;
483 break;
484 }
485 }
486
487 return NOERROR;
488}
489
490/*********************************************************************************************************************************************************************/
491/********************************************************************** BUILD SUPER LAYER SEEDS **********************************************************************/
492/*********************************************************************************************************************************************************************/
493
494//---------------------
495// Find_SuperLayerSeeds
496//---------------------
497void DTrackCandidate_factory_CDC::Find_SuperLayerSeeds(deque<DCDCTrkHit*>& locSuperLayerHits, unsigned int locSuperLayer)
498{
499 // Sort through hits ring by ring to find DCDCRingSeed's from neighboring wires in the same ring.
500 // What we want is a list of DCDCRingSeed's for each ring, which will then be combined to form DCDCSuperLayerSeeds
501 // Each DCDCRingSeed is a list of adjacent hits ordered by straw number.
502 // If a DCDCRingSeed crosses the straw = 1 barrier:
503 // Then the first hit is the smallest straw with phi > pi, and the last hit is the largest straw with phi < pi
504
505 // Clear DCDCSuperLayerSeed's
506 deque<DCDCSuperLayerSeed*>& locSuperLayerSeeds = dSuperLayerSeeds[locSuperLayer - 1];
507 locSuperLayerSeeds.clear();
508
509 DCDCRingSeed locCDCRingSeed;
510 deque<DCDCRingSeed> locCDCRingSeeds; //list of DCDCRingSeed's in a given ring
511 deque<deque<DCDCRingSeed> > rings; //1st dimension is ring, 2nd dimension is DCDCRingSeed's in that ring
512 int last_ring = -1;
513
514 for(size_t i = 0; i < locSuperLayerHits.size(); ++i)
515 {
516 DCDCTrkHit *trkhit = locSuperLayerHits[i];
517 if(DEBUG_LEVEL > 20)
518 cout << "track hit ring, straw = " << trkhit->hit->wire->ring << ", " << trkhit->hit->wire->straw << endl;
519
520 // Check if ring number has changed.
521 if(trkhit->hit->wire->ring != last_ring)
522 {
523 if(DEBUG_LEVEL > 20)
524 cout << "new ring, last ring = " << trkhit->hit->wire->ring << ", " << last_ring << endl;
525 //ring # has changed: save the current DCDCRingSeed (from the previous ring) (if not empty)
526 if(!locCDCRingSeed.hits.empty())
527 locCDCRingSeeds.push_back(locCDCRingSeed);
528 //if > 1 DCDCRingSeed on the previous ring: compare first and last DCDCRingSeeds
529 //if they are adjacent (extending through the straw = 1 boundary): merge DCDCRingSeeds
530 if(locCDCRingSeeds.size() > 1)
531 {
532 unsigned int locMinStraw = locCDCRingSeeds[0].hits[0]->hit->wire->straw;
533 unsigned int locMaxStraw = locCDCRingSeeds[locCDCRingSeeds.size() - 1].hits[locCDCRingSeeds[locCDCRingSeeds.size() - 1].hits.size() - 1]->hit->wire->straw;
534 unsigned int locNumStrawsInRing = dNumStrawsPerRing[locCDCRingSeeds[0].hits[0]->hit->wire->ring - 1];
535 if((locMinStraw + locNumStrawsInRing - locMaxStraw) <= 1) //merge ringseeds
536 {
537 if(DEBUG_LEVEL > 20)
538 cout << "straw boundary: merge ringseeds" << endl;
539 locCDCRingSeeds[0].hits.insert(locCDCRingSeeds[0].hits.begin(), locCDCRingSeeds[locCDCRingSeeds.size() - 1].hits.begin(), locCDCRingSeeds[locCDCRingSeeds.size() - 1].hits.end());
540 //insert at beginning: straws now arranged as: ..., N - 2, N - 1, N, 1, 2, 3, ...
541 locCDCRingSeeds.pop_back();
542 }
543 }
544 //if there was at least one DCDCRingSeed found on the previous ring, save it in the 2d deque
545 if(!locCDCRingSeeds.empty())
546 rings.push_back(locCDCRingSeeds);
547 if(DEBUG_LEVEL > 3)
548 cout << " ringseed hits:" << locCDCRingSeed.hits.size() << " locCDCRingSeeds:" << locCDCRingSeeds.size() << endl;
549 //reset for finding the next group of hits
550 locCDCRingSeeds.clear();
551 locCDCRingSeed.hits.clear();
552 //save this hit and continue
553 locCDCRingSeed.hits.push_back(trkhit);
554 locCDCRingSeed.ring = trkhit->hit->wire->ring;
555 locCDCRingSeed.linked = false;
556 last_ring = trkhit->hit->wire->ring;
557 continue;
558 }
559
560 // Check if this hit is a neighbor of the last hit added to the ringseed
561 if((unsigned int)abs(locCDCRingSeed.hits[locCDCRingSeed.hits.size() - 1]->hit->wire->straw - trkhit->hit->wire->straw) > 1)
562 {
563 //not a neighbor: save old and create new ringseed
564 if(DEBUG_LEVEL > 20)
565 cout << "straw diff" << endl;
566 if(!locCDCRingSeed.hits.empty())
567 locCDCRingSeeds.push_back(locCDCRingSeed);
568 if(DEBUG_LEVEL > 3)
569 cout << "ringseed hits: " << locCDCRingSeed.hits.size() << endl;
570 locCDCRingSeed.hits.clear();
571 locCDCRingSeed.linked = false;
572 }
573
574 locCDCRingSeed.hits.push_back(trkhit);
575 if(DEBUG_LEVEL > 20)
576 cout << "push back hit straw = " << trkhit->hit->wire->straw << endl;
577 }
578 //save final seeds, check if need to merge
579 if(!locCDCRingSeed.hits.empty())
580 locCDCRingSeeds.push_back(locCDCRingSeed);
581 if(locCDCRingSeeds.size() > 1)
582 {
583 //compare first and last ringseeds: if ringseed extends through straw boundary, merge ringseeds
584 unsigned int locMinStraw = locCDCRingSeeds[0].hits[0]->hit->wire->straw;
585 unsigned int locMaxStraw = locCDCRingSeeds[locCDCRingSeeds.size() - 1].hits[locCDCRingSeeds[locCDCRingSeeds.size() - 1].hits.size() - 1]->hit->wire->straw;
586 unsigned int locNumStrawsInRing = dNumStrawsPerRing[locCDCRingSeeds[0].hits[0]->hit->wire->ring - 1];
587 if((locMinStraw + locNumStrawsInRing - locMaxStraw) <= 1) //merge ringseeds
588 {
589 if(DEBUG_LEVEL > 20)
590 cout << "straw boundary: merge ringseeds" << endl;
591 locCDCRingSeeds[0].hits.insert(locCDCRingSeeds[0].hits.begin(), locCDCRingSeeds[locCDCRingSeeds.size() - 1].hits.begin(), locCDCRingSeeds[locCDCRingSeeds.size() - 1].hits.end());
592 //insert at beginning: straws now arranged as: ..., N - 2, N - 1, N, 1, 2, 3, ...
593 locCDCRingSeeds.pop_back();
594 }
595 }
596 if(!locCDCRingSeeds.empty())
597 rings.push_back(locCDCRingSeeds);
598 if(DEBUG_LEVEL > 3)
599 cout << " ringseed hits:" << locCDCRingSeed.hits.size() << " ringseeds:" << locCDCRingSeeds.size() << endl;
600 if(DEBUG_LEVEL > 3)
601 cout << "rings: " << rings.size() << endl;
602
603 // Print all DCDCRingSeeds to screen
604 if(DEBUG_LEVEL > 45)
605 {
606 for(size_t i = 0; i < rings.size(); ++i)
607 {
608 for(size_t k = 0; k < rings[i].size(); ++k)
609 {
610 cout << "hits for ringseed ring, seed indices " << i << ", " << k << ":" << endl;
611 for(size_t j = 0; j < rings[i][k].hits.size(); ++j)
612 cout << "wire ring, straw = " << rings[i][k].hits[j]->hit->wire->ring << ", " << rings[i][k].hits[j]->hit->wire->straw << endl;
613 }
614 }
615 }
616
617 // If we have no rings, then there must be no super layer seeds. Bail now.
618 if(rings.empty())
619 return;
620
621 // Loop over rings, creating DCDCSuperLayerSeed's from adjacent rings
622 for(ringiter ring = rings.begin(); ring != rings.end(); ++ring)
623 {
624 deque<DCDCRingSeed>& locCDCRingSeeds = *ring;
625 ringiter next_ring = ring;
626 ++next_ring;
627
628 // Loop over ringseeds of this ring
629 for(size_t j = 0; j < locCDCRingSeeds.size(); ++j)
630 {
631 if(locCDCRingSeeds[j].linked)
632 continue;
633
634 // This ringseed hasn't been used in a DCDCSuperLayerSeed yet. Start a new seed with it.
635 deque<DCDCRingSeed*> parent;
636 parent.push_back(&locCDCRingSeeds[j]);
637 Link_RingSeeds(parent, next_ring, rings.end(), locSuperLayer, 0);
638 }
639 }
640
641 // Set wire orientations
642 for(size_t loc_i = 0; loc_i < locSuperLayerSeeds.size(); ++loc_i)
643 {
644 locSuperLayerSeeds[loc_i]->dSuperLayer = locSuperLayer;
645 locSuperLayerSeeds[loc_i]->dSeedIndex = loc_i;
646 if((locSuperLayer == 7) || (locSuperLayer == 4) || (locSuperLayer == 1))
647 locSuperLayerSeeds[loc_i]->dWireOrientation = WIRE_DIRECTION_AXIAL;
648 else if((locSuperLayer == 2) || (locSuperLayer == 6))
649 locSuperLayerSeeds[loc_i]->dWireOrientation = WIRE_DIRECTION_STEREOLEFT;
650 else
651 locSuperLayerSeeds[loc_i]->dWireOrientation = WIRE_DIRECTION_STEREORIGHT;
652 }
653}
654
655//---------------
656// Link_RingSeeds
657//---------------
658void DTrackCandidate_factory_CDC::Link_RingSeeds(deque<DCDCRingSeed*>& parent, ringiter ring, ringiter ringend, unsigned int locSuperLayer, unsigned int locNumPreviousRingsWithoutHit)
659{
660 /// Combine DCDCRingSeed's from rings into DCDCSuperLayerSeed's
661 ///
662 /// This a a re-entrant routine (i.e. it calls itself recursively). Upon
663 /// entry, <i>parent</i> contains a list of pointers to all of the ringseeds
664 /// from the rings outside of <i>ring</i> that are to be combined into
665 /// a seed. This will search through all ringseeds of <i>ring</i> and if
666 /// any are found that can extend the parent, a copy of parent is made,
667 /// the current ringseed of this ring is added to it, and then it is
668 /// passed on to another call to this routine. If no matches are found,
669 /// then it will try skipping a ring to find matches (if enabled).
670 /// If still no matches are found (which will be the case for the outer-most ring), then
671 /// the ringseeds in <i>parent</i> will be combined into a single DCDCSuperLayerSeed.
672
673 // Make sure parent has at least one ringseed
674 if(parent.empty())
675 {
676 cout << "parent has no ringseeds!!" << endl;
677 return;
678 }
679
680 // Set flag to keep track of whether this is the end of the seed or not
681 bool seed_extended = false;
682 if(ring != ringend)
683 {
684 // Last ringseed in parent list is the one we need to compare to
685 DCDCRingSeed *parent_ringseed = parent[parent.size() - 1];
686 double r_parent = parent_ringseed->hits[0]->hit->wire->origin.Perp();
687
688 // Loop over ringseeds in this ring
689 deque<DCDCRingSeed> &locCDCRingSeeds = (*ring);
690 ++ring; // increment ring iterator to point to next level down in case we recall ouself below
691
692 for(size_t i = 0; i < locCDCRingSeeds.size(); ++i)
693 {
694 // Calculate the transverse (to the beamline) distance between the two DCDCRingSeed's
695 double dr = r_parent - locCDCRingSeeds[i].hits[0]->hit->wire->origin.Perp();
696 double locTransverseDist2 = fabs(MinDist2(locCDCRingSeeds[i], *parent_ringseed) - dr*dr);
697 // Check if this ringseed is close enough to the parent's to link them together
698 if(DEBUG_LEVEL > 20)
699 cout << "ring1, ring2, locTransverseDist2, MAX_HIT_DIST2, dr*dr = " << locCDCRingSeeds[i].hits[0]->hit->wire->ring << ", " << parent_ringseed->hits[0]->hit->wire->ring << ", " << locTransverseDist2 << ", " << MAX_HIT_DIST2 << ", " << dr*dr << endl;
700 if(locTransverseDist2 < MAX_HIT_DIST2)
701 {
702 // link them together
703 deque<DCDCRingSeed*> myparent = parent;
704 myparent.push_back(&locCDCRingSeeds[i]);
705 locCDCRingSeeds[i].linked = true;
706 // recursive call: try to link this grouping of DCDCRingSeed's to a DCDCRingSeed in the next ring
707 Link_RingSeeds(myparent, ring, ringend, locSuperLayer, 0);
708 seed_extended = true;
709 }
710 }
711 if((!seed_extended) && (locNumPreviousRingsWithoutHit < MAX_NUM_RINGSEED_RINGS_SKIPABLE))
712 {
713 // no link was found, but try to skip this ring and find a match in the next ring
714 Link_RingSeeds(parent, ring, ringend, locSuperLayer, locNumPreviousRingsWithoutHit + 1);
715 seed_extended = true;
716 }
717 }
718
719 // Check if this is the end of the line.
720 if(!seed_extended)
721 {
722 // This is the end of this seed.
723 // Check if this seed contains a spiral.
724 int locSpiralRingIndex = -1;
725 for(size_t i = 0; i < parent.size(); ++i)
726 {
727 if(parent[i]->hits.size() < MIN_STRAWS_DEFINITE_SPIRAL_TURN)
728 continue;
729 locSpiralRingIndex = i;
730 break;
731 }
732
733 // Check whether this seed is an obvious intersection of two tracks (with one of them a spiral)
734 bool locSeparateSeedsFlag = false;
735 if((locSpiralRingIndex != -1) && (parent.size() > 1))
736 {
737 double locAvgNumHitsInNonSpiralRing = 0.0;
738 for(size_t i = 0; i < parent.size(); ++i)
739 {
740 if(int(i) == locSpiralRingIndex)
741 continue;
742 locAvgNumHitsInNonSpiralRing += parent[i]->hits.size();
743 }
744 locAvgNumHitsInNonSpiralRing /= double(parent.size() - 1);
745 if(locAvgNumHitsInNonSpiralRing < 2)
746 locSeparateSeedsFlag = true;
747 }
748
749 //if obvious intersection: save spiral ring-seed separately
750 if(locSeparateSeedsFlag && (parent[locSpiralRingIndex]->hits.size() >= MIN_SEED_HITS))
751 {
752 DCDCSuperLayerSeed* locSuperLayerSeed = Get_Resource_CDCSuperLayerSeed();
753 for(size_t loc_i = 0; loc_i < parent[locSpiralRingIndex]->hits.size(); ++loc_i)
754 parent[locSpiralRingIndex]->hits[loc_i]->flags |= USED;
755 dSuperLayerSeeds[locSuperLayer - 1].push_back(locSuperLayerSeed);
756 locSuperLayerSeed->dCDCRingSeeds.push_back(*(parent[locSpiralRingIndex]));
757 }
758
759 //save normal seed if enough hits
760 unsigned int locTotalNumHits = 0;
761 for(size_t i = 0; i < parent.size(); ++i)
762 {
763 if((int(i) == locSpiralRingIndex) && locSeparateSeedsFlag)
764 continue;
765 locTotalNumHits += parent[i]->hits.size();
766 }
767 if(locTotalNumHits < MIN_SEED_HITS)
768 {
769 if(DEBUG_LEVEL > 10)
770 cout << "rejecting seed due to too few hits (have " << locTotalNumHits << " need " << MIN_SEED_HITS << ")" << endl;
771 return;
772 }
773
774 DCDCSuperLayerSeed* locSuperLayerSeed = Get_Resource_CDCSuperLayerSeed();
775 for(size_t i = 0; i < parent.size(); ++i)
776 {
777 if((int(i) == locSpiralRingIndex) && locSeparateSeedsFlag)
778 continue;
779 locSuperLayerSeed->dCDCRingSeeds.push_front(*(parent[i])); //input rings were in reverse order!!
780 for(size_t loc_j = 0; loc_j < parent[i]->hits.size(); ++loc_j)
781 parent[i]->hits[loc_j]->flags |= USED;
782 }
783 dSuperLayerSeeds[locSuperLayer - 1].push_back(locSuperLayerSeed);
784 }
785}
786
787//---------
788// MinDist2
789//---------
790double DTrackCandidate_factory_CDC::MinDist2(const DCDCRingSeed& locInnerRingSeed, const DCDCRingSeed& locOuterRingSeed)
791{
792 const deque<DCDCTrkHit*>& locInnerSeedHits = locInnerRingSeed.hits;
793 const deque<DCDCTrkHit*>& locOuterSeedHits = locOuterRingSeed.hits;
794 return MinDist2(locInnerSeedHits, locOuterSeedHits);
795}
796
797//---------
798// MinDist2
799//---------
800double DTrackCandidate_factory_CDC::MinDist2(const deque<DCDCTrkHit*>& locInnerSeedHits, const deque<DCDCTrkHit*>& locOuterSeedHits)
801{
802 /// Returns the minimum distance squared between the two seeds. Assumes all of the hits in a given set are on the same ring.
803 /// First it checks if the two seeds overlap in phi: if so, then the radial difference between the rings (squared) is returned.
804 /// Otherwise, only the first and last hits of the adjacent rings between each seed's hit list are used.
805 /// to calculate a maximum of 4 distances (minimum of 1), of which the smallest is returned.
806 if(locInnerSeedHits.empty() || locOuterSeedHits.empty())
807 {
808 cout << "Number of seed hits 0! (Ninner = " << locInnerSeedHits.size() << " ,Nouter = " << locOuterSeedHits.size() << ")" << endl;
809 return 1.0E10;
810 }
811
812 DCDCTrkHit* locInnermostRingFirstStrawHit = locInnerSeedHits.front();
813 DCDCTrkHit* locInnermostRingLastStrawHit = locInnerSeedHits.back();
814 DCDCTrkHit* locOutermostRingFirstStrawHit = locOuterSeedHits.front();
815 DCDCTrkHit* locOutermostRingLastStrawHit = locOuterSeedHits.back();
816
817 //see if seeds overlap in phi
818 float locInnermostRingFirstStrawPhi = locInnermostRingFirstStrawHit->hit->wire->phi;
819 float locInnermostRingLastStrawPhi = locInnermostRingLastStrawHit->hit->wire->phi;
820 float locOutermostRingFirstStrawPhi = locOutermostRingFirstStrawHit->hit->wire->phi;
821 float locOutermostRingLastStrawPhi = locOutermostRingLastStrawHit->hit->wire->phi;
822 if(DEBUG_LEVEL > 100)
823 cout << "inner ring: ring, first/last straws & phis = " << locInnermostRingFirstStrawHit->hit->wire->ring << ", " << locInnermostRingFirstStrawHit->hit->wire->straw << ", " << locInnermostRingLastStrawHit->hit->wire->straw << ", " << locInnermostRingFirstStrawPhi << ", " << locInnermostRingLastStrawPhi << endl;
824 if(DEBUG_LEVEL > 100)
825 cout << "outer ring: ring, first/last straws & phis = " << locOutermostRingFirstStrawHit->hit->wire->ring << ", " << locOutermostRingFirstStrawHit->hit->wire->straw << ", " << locOutermostRingLastStrawHit->hit->wire->straw << ", " << locOutermostRingFirstStrawPhi << ", " << locOutermostRingLastStrawPhi << endl;
826
827 //account for phi = 0/2pi boundary
828 bool locInnerRingCrossesBoundaryFlag = (locInnermostRingLastStrawPhi < locInnermostRingFirstStrawPhi);
829 bool locOuterRingCrossesBoundaryFlag = (locOutermostRingLastStrawPhi < locOutermostRingFirstStrawPhi);
830 if(DEBUG_LEVEL > 100)
831 cout << "in/out boundary flags = " << locInnerRingCrossesBoundaryFlag << ", " << locOuterRingCrossesBoundaryFlag << endl;
832 if(locOuterRingCrossesBoundaryFlag)
833 locOutermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
834 if(locInnerRingCrossesBoundaryFlag)
835 locInnermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
836 if(locOuterRingCrossesBoundaryFlag & (!locInnerRingCrossesBoundaryFlag) && ((locOutermostRingLastStrawPhi - locInnermostRingLastStrawPhi) > M_PI3.14159265358979323846))
837 {
838 locInnermostRingFirstStrawPhi += M_TWO_PI6.28318530717958647692;
839 locInnermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
840 }
841 if(locInnerRingCrossesBoundaryFlag & (!locOuterRingCrossesBoundaryFlag) && ((locInnermostRingLastStrawPhi - locOutermostRingLastStrawPhi) > M_PI3.14159265358979323846))
842 {
843 locOutermostRingFirstStrawPhi += M_TWO_PI6.28318530717958647692;
844 locOutermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
845 }
846
847 if(DEBUG_LEVEL > 100)
848 cout << "final inner ring: ring, first/last straws & phis = " << locInnermostRingFirstStrawHit->hit->wire->ring << ", " << locInnermostRingFirstStrawHit->hit->wire->straw << ", " << locInnermostRingLastStrawHit->hit->wire->straw << ", " << locInnermostRingFirstStrawPhi << ", " << locInnermostRingLastStrawPhi << endl;
849 if(DEBUG_LEVEL > 100)
850 cout << "final outer ring: ring, first/last straws & phis = " << locOutermostRingFirstStrawHit->hit->wire->ring << ", " << locOutermostRingFirstStrawHit->hit->wire->straw << ", " << locOutermostRingLastStrawHit->hit->wire->straw << ", " << locOutermostRingFirstStrawPhi << ", " << locOutermostRingLastStrawPhi << endl;
851
852 //finally check for overlaps
853 double dr = locOutermostRingLastStrawHit->hit->wire->origin.Perp() - locInnermostRingFirstStrawHit->hit->wire->origin.Perp();
854 if((locOutermostRingFirstStrawPhi >= locInnermostRingFirstStrawPhi) && (locOutermostRingFirstStrawPhi <= locInnermostRingLastStrawPhi))
855 return dr*dr;
856 if((locOutermostRingLastStrawPhi >= locInnermostRingFirstStrawPhi) && (locOutermostRingLastStrawPhi <= locInnermostRingLastStrawPhi))
857 return dr*dr;
858 if((locInnermostRingFirstStrawPhi >= locOutermostRingFirstStrawPhi) && (locInnermostRingFirstStrawPhi <= locOutermostRingLastStrawPhi))
859 return dr*dr; //4th case not needed. this case only needed if innermost ring is one wire across
860
861 //no overlap, make all 4 comparisons between hits
862 double d2, d2min;
863 d2min = locInnermostRingFirstStrawHit->Dist2(locOutermostRingFirstStrawHit);
864 if(locOutermostRingFirstStrawHit != locOutermostRingLastStrawHit)
865 {
866 d2 = locInnermostRingFirstStrawHit->Dist2(locOutermostRingLastStrawHit);
867 if(d2 < d2min)
868 d2min = d2;
869 }
870 if(locInnermostRingFirstStrawHit == locInnermostRingLastStrawHit)
871 return d2min;
872
873 d2 = locInnermostRingLastStrawHit->Dist2(locOutermostRingFirstStrawHit);
874 if(d2 < d2min)
875 d2min = d2;
876 if(locOutermostRingFirstStrawHit != locOutermostRingLastStrawHit)
877 {
878 d2 = locInnermostRingLastStrawHit->Dist2(locOutermostRingLastStrawHit);
879 if(d2 < d2min)
880 d2min = d2;
881 }
882
883 return d2min;
884}
885
886//---------------------------------------
887// Reject_SuperLayerSeeds_HighSeedDensity
888//---------------------------------------
889void DTrackCandidate_factory_CDC::Reject_SuperLayerSeeds_HighSeedDensity(unsigned int locSuperLayer)
890{
891 //The track finding algorithm will grind to a halt if there are too many super layer seeds in a given area
892 //e.g. A slow spiral pion that loses energy very slowly will loop around many, many times before stopping,
893 //sometimes resulting in 40+ super layer seeds in a given super layer.
894 //Therefore, if the density of super layer seeds in a given region is too high, reject all super layer seeds passing through that region of space, except for the ones on the edges
895 //It will be impossible to determine track parameters in these regions anyway, so may as well reject them.
896
897 if(SEED_DENSITY_BIN_STRAW_WIDTH == 0)
898 return; //rejection disabled
899
900 deque<DCDCSuperLayerSeed*>& locSuperLayerSeeds = dSuperLayerSeeds[locSuperLayer - 1];
901 if(locSuperLayerSeeds.size() <= MAX_SEEDS_IN_STRAW_BIN)
902 return; //not enough for there to even possibly be an issue
903
904 // histogram phis of all seeds within this super layer
905 // We use a simple array to store our histogram here. We don't want to use ROOT histograms because they are not thread safe.
906 // Setup histogram
907 unsigned int hist[dNumSeedDensityPhiBins];
908 for(unsigned int i = 0; i < dNumSeedDensityPhiBins; ++i)
909 hist[i] = 0; // clear histogram
910 double bin_width = M_TWO_PI6.28318530717958647692/(double)dNumSeedDensityPhiBins;
911 double hist_low_limit = 0.0; // lower edge of histogram limits
912
913 //Find phi ranges of super layer seeds: store in map & histogram them
914 map<unsigned int, pair<double, double> > locMapPhiRanges; //key is seed index, pair is phi range (first/last) //first > last if passes through phi = 0 boundary
915 for(size_t loc_i = 0; loc_i < locSuperLayerSeeds.size(); ++loc_i)
916 {
917 double locSeedFirstPhi, locSeedLastPhi;
918 Calc_SuperLayerPhiRange(locSuperLayerSeeds[loc_i], locSeedFirstPhi, locSeedLastPhi);
919 locMapPhiRanges[locSuperLayerSeeds[loc_i]->dSeedIndex] = pair<double, double>(locSeedFirstPhi, locSeedLastPhi);
920 if(DEBUG_LEVEL > 20)
921 cout << "super layer, seed index, first phi, last phi = " << locSuperLayer << ", " << locSuperLayerSeeds[loc_i]->dSeedIndex << ", " << locSeedFirstPhi << ", " << locSeedLastPhi << endl;
922
923 unsigned int locFirstPhiBin = (unsigned int)((locSeedFirstPhi - hist_low_limit)/bin_width);
924 unsigned int locLastPhiBin = (unsigned int)((locSeedLastPhi - hist_low_limit)/bin_width);
925 for(unsigned int locPhiBin = locFirstPhiBin; locPhiBin <= locLastPhiBin; ++locPhiBin)
926 ++hist[locPhiBin];
927 }
928
929 //determine search window size:
930 unsigned int locOuterRing = superlayer_boundaries[locSuperLayer - 1];
931 unsigned int locAverageNumStrawsInRing = (dNumStrawsPerRing[locOuterRing - 4] + dNumStrawsPerRing[locOuterRing - 1])/2; //I know it floored; it's close enough
932 double locSearchBinPhiSize = double(SEED_DENSITY_BIN_STRAW_WIDTH)*M_TWO_PI6.28318530717958647692/double(locAverageNumStrawsInRing);
933
934 //find the search start point: try to start somewhere where there are no seeds for a range that is at least as large as the window; else start at 0
935 int locStartPhiBin = -1;
936 for(unsigned int locPhiBin = 0; locPhiBin < dNumSeedDensityPhiBins; ++locPhiBin)
937 {
938 if(hist[locPhiBin] > 0)
939 {
940 locStartPhiBin = -1;
941 continue;
942 }
943 if(locStartPhiBin == -1)
944 locStartPhiBin = locPhiBin;
945 else if((locPhiBin - locStartPhiBin) > locSearchBinPhiSize)
946 break;
947 }
948 if(locStartPhiBin == -1)
949 locStartPhiBin = 0;
950
951 // loop over phi range, scanning with a window of size "locSearchBinPhiSize," finding where the density of seeds is too high and marking those seeds for rejection
952 set<unsigned int> locSeedsToReject;
953 for(unsigned int locPhiBin = 0; locPhiBin < dNumSeedDensityPhiBins; ++locPhiBin)
954 {
955 unsigned int locReadPhiBin = locStartPhiBin + locPhiBin;
956 if(locReadPhiBin >= dNumSeedDensityPhiBins)
957 locReadPhiBin -= dNumSeedDensityPhiBins;
958
959 double locWindowPhiRangeMin = hist_low_limit + bin_width*(double(locReadPhiBin));
960 if(locWindowPhiRangeMin >= M_TWO_PI6.28318530717958647692)
961 locWindowPhiRangeMin -= M_TWO_PI6.28318530717958647692;
962 double locWindowPhiRangeMax = locWindowPhiRangeMin + locSearchBinPhiSize;
963
964 map<unsigned int, pair<double, double> >::const_iterator locSeedIterator = locMapPhiRanges.begin();
965 vector<unsigned int> locSeedsInThisRange;
966 for(; locSeedIterator != locMapPhiRanges.end(); ++locSeedIterator)
967 {
968 double locSeedPhiRangeMin = locSeedIterator->second.first;
969 double locSeedPhiRangeMax = locSeedIterator->second.second;
970 if(Check_IfPhiRangesOverlap(locSeedPhiRangeMin, locSeedPhiRangeMax, locWindowPhiRangeMin, locWindowPhiRangeMax))
971 locSeedsInThisRange.push_back(locSeedIterator->first);
972 }
973 if(locSeedsInThisRange.size() <= MAX_SEEDS_IN_STRAW_BIN)
974 continue;
975
976 //mark these seeds for deletion
977 for(size_t loc_i = 0; loc_i < locSeedsInThisRange.size(); ++loc_i)
978 locSeedsToReject.insert(locSeedsInThisRange[loc_i]);
979 }
980
981 //loop over seeds marked for rejection: keep the first and last seeds of each group
982 //ignore phi = 0 barrier for now
983 //also, mark phi regions as bad
984 set<unsigned int>::const_iterator locRejectIterator = locSeedsToReject.begin();
985 int locBeginIndex = -1, locPreviousIndex = 0, locFirstIndex = 0, locEndIndex = 0;
986 set<unsigned int> locSeedsToNotReject;
987 for(; locRejectIterator != locSeedsToReject.end(); ++locRejectIterator)
988 {
989 unsigned int locCurrentIndex = *locRejectIterator;
990 if(DEBUG_LEVEL > 15)
991 cout << "Marked for rejection: super layer, seed index = " << locSuperLayer << ", " << locCurrentIndex << endl;
992 if(locBeginIndex == -1)
993 {
994 locFirstIndex = locCurrentIndex;
995 locBeginIndex = locCurrentIndex;
996 locSeedsToNotReject.insert(locBeginIndex);
997 if(DEBUG_LEVEL > 15)
998 cout << "don't reject: " << locBeginIndex << endl;
999 }
1000 if(DEBUG_LEVEL > 30)
1001 cout << "window size, current phis, previous phis = " << locSearchBinPhiSize << ", " << locMapPhiRanges[locCurrentIndex].first << ", " << locMapPhiRanges[locCurrentIndex].second << ", " << locMapPhiRanges[locPreviousIndex].first << ", " << locMapPhiRanges[locPreviousIndex].second << endl;
1002 if(Check_IfPhiRangesOverlap(locMapPhiRanges[locCurrentIndex].first, locMapPhiRanges[locCurrentIndex].second, locMapPhiRanges[locPreviousIndex].first, locMapPhiRanges[locPreviousIndex].second + locSearchBinPhiSize))
1003 {
1004 locPreviousIndex = locCurrentIndex;
1005 locEndIndex = locCurrentIndex;
1006 continue;
1007 }
1008 if(Check_IfPhiRangesOverlap(locMapPhiRanges[locCurrentIndex].first, locMapPhiRanges[locCurrentIndex].second, locMapPhiRanges[locPreviousIndex].first - locSearchBinPhiSize, locMapPhiRanges[locPreviousIndex].second))
1009 {
1010 locPreviousIndex = locCurrentIndex;
1011 locEndIndex = locCurrentIndex;
1012 continue;
1013 }
1014
1015 //seed isn't within locSearchBinPhiSize of previous seed: edge
1016 if(DEBUG_LEVEL > 15)
1017 cout << "Unmark for rejection: super layer, seed indexes = " << locSuperLayer << ", " << locBeginIndex << ", " << locPreviousIndex << endl;
1018
1019 //too many seeds in this region: in future super layers, don't assume unmatched seeds in this region are new tracks
1020 dRejectedPhiRegions[locSuperLayer - 1].push_back(pair<double, double>(locMapPhiRanges[locBeginIndex].first, locMapPhiRanges[locPreviousIndex].second));
1021
1022 locSeedsToNotReject.insert(locPreviousIndex);
1023 locSeedsToNotReject.insert(locCurrentIndex); //beginning of new section
1024 locBeginIndex = locCurrentIndex;
1025 locPreviousIndex = locCurrentIndex;
1026 locEndIndex = locCurrentIndex;
1027 }
1028 locSeedsToNotReject.insert(locEndIndex); //don't reject the last one //will check overlap below
1029
1030 if(DEBUG_LEVEL > 30)
1031 cout << "first phis, last phis = " << locMapPhiRanges[locFirstIndex].first << ", " << locMapPhiRanges[locFirstIndex].second << ", " << locMapPhiRanges[locEndIndex].first << ", " << locMapPhiRanges[locEndIndex].second << endl;
1032
1033 //check to see if last overlaps with first //overlap across phi = 0 barrier
1034 if(Check_IfPhiRangesOverlap(locMapPhiRanges[locFirstIndex].first, locMapPhiRanges[locFirstIndex].second, locMapPhiRanges[locEndIndex].first, locMapPhiRanges[locEndIndex].second))
1035 {
1036 if(DEBUG_LEVEL > 15)
1037 cout << "re-reject first/last = " << locFirstIndex << ", " << locEndIndex << endl;
1038 //do reject them
1039 locSeedsToNotReject.erase(locFirstIndex);
1040 locSeedsToNotReject.erase(locEndIndex);
1041 }
1042
1043
1044 // reject (and recycle) the seeds in areas where the seeds were too dense
1045 for(deque<DCDCSuperLayerSeed*>::iterator locDequeIterator = locSuperLayerSeeds.begin(); locDequeIterator != locSuperLayerSeeds.end();)
1046 {
1047 unsigned int locSeedIndex = (*locDequeIterator)->dSeedIndex;
1048 if((locSeedsToReject.find(locSeedIndex) != locSeedsToReject.end()) && (locSeedsToNotReject.find(locSeedIndex) == locSeedsToNotReject.end()))
1049 {
1050 if(DEBUG_LEVEL > 10)
1051 cout << "seed density too high, reject seed: " << locSeedIndex << endl;
1052 dCDCSuperLayerSeedPool_Available.push_back(*locDequeIterator); //recycle memory
1053 locDequeIterator = locSuperLayerSeeds.erase(locDequeIterator);
1054 }
1055 else
1056 ++locDequeIterator;
1057 }
1058}
1059
1060//------------------------
1061// Calc_SuperLayerPhiRange
1062//------------------------
1063void DTrackCandidate_factory_CDC::Calc_SuperLayerPhiRange(DCDCSuperLayerSeed* locSuperLayerSeed, double& locSeedFirstPhi, double& locSeedLastPhi)
1064{
1065 // Calculate the phi-range across which the DCDCSuperLayerSeed extends.
1066 locSeedFirstPhi = 9.9E9;
1067 locSeedLastPhi = -9.9E9;
1068 for(size_t loc_j = 0; loc_j < locSuperLayerSeed->dCDCRingSeeds.size(); ++loc_j)
1069 {
1070 DCDCTrkHit *locFirstStrawHit = locSuperLayerSeed->dCDCRingSeeds[loc_j].hits.front();
1071 DCDCTrkHit *locLastStrawHit = locSuperLayerSeed->dCDCRingSeeds[loc_j].hits.back();
1072
1073 double locRingFirstPhi = locFirstStrawHit->hit->wire->phi;
1074 if(locRingFirstPhi < 0.0)
1075 locRingFirstPhi += M_TWO_PI6.28318530717958647692;
1076 double locRingLastPhi = locLastStrawHit->hit->wire->phi;
1077 if(locRingLastPhi < 0.0)
1078 locRingLastPhi += M_TWO_PI6.28318530717958647692;
1079 if(loc_j == 0)
1080 {
1081 locSeedFirstPhi = locRingFirstPhi;
1082 locSeedLastPhi = locRingLastPhi;
1083 continue;
1084 }
1085
1086 if(locSeedFirstPhi > locSeedLastPhi) //seed goes across phi = 0 boundary
1087 {
1088 if(locRingFirstPhi > locRingLastPhi) //ring goes across phi = 0 boundary
1089 {
1090 if(locRingFirstPhi < locSeedFirstPhi)
1091 locSeedFirstPhi = locRingFirstPhi;
1092 if(locRingLastPhi > locSeedLastPhi)
1093 locSeedLastPhi = locRingLastPhi;
1094 }
1095 else
1096 {
1097 if((locRingFirstPhi > M_PI3.14159265358979323846) && (locRingFirstPhi < locSeedFirstPhi))
1098 locSeedFirstPhi = locRingFirstPhi;
1099 else if((locRingLastPhi < M_PI3.14159265358979323846) && (locRingLastPhi > locSeedLastPhi))
1100 locSeedLastPhi = locRingLastPhi;
1101 }
1102 }
1103 else //seed does not (so far) go across phi = 0 boundary
1104 {
1105 if(locRingFirstPhi > locRingLastPhi) //ring goes across phi = 0 boundary
1106 {
1107 locSeedFirstPhi = locRingFirstPhi;
1108 if(locRingLastPhi > locSeedLastPhi)
1109 locSeedLastPhi = locRingLastPhi;
1110 }
1111 else
1112 {
1113 if(locRingFirstPhi < locSeedFirstPhi)
1114 locSeedFirstPhi = locRingFirstPhi;
1115 if(locRingLastPhi > locSeedLastPhi)
1116 locSeedLastPhi = locRingLastPhi;
1117 }
1118 }
1119 }
1120}
1121
1122//-------------------------
1123// Check_IfPhiRangesOverlap
1124//-------------------------
1125bool DTrackCandidate_factory_CDC::Check_IfPhiRangesOverlap(double locFirstSeedPhi, double locLastSeedPhi, double locTargetFirstPhi, double locTargetLastPhi)
1126{
1127 //if first phi > last phi 2nd, then it extends through the phi = 0 boundary
1128 if(locFirstSeedPhi > locLastSeedPhi) //seed extends through phi = 0 boundary
1129 {
1130 if(locTargetFirstPhi > locTargetLastPhi) //hist range extends through phi = 0 boundary
1131 return true; //clearly both intersect: both cross phi = 0
1132 else
1133 {
1134//S: F---|---L
1135//H: FXXXL | FXXXL
1136 if(locTargetLastPhi > locFirstSeedPhi)
1137 return true;
1138 else if(locTargetFirstPhi < locLastSeedPhi)
1139 return true;
1140 }
1141 }
1142 else //seed does not extend through phi = 0 boundary
1143 {
1144 if(locTargetFirstPhi > locTargetLastPhi) //hist range extends through phi = 0 boundary
1145 {
1146//H: F---|---L
1147//S: FXXXL | FXXXL
1148 if(locLastSeedPhi > locTargetFirstPhi)
1149 return true;
1150 else if(locFirstSeedPhi < locTargetLastPhi)
1151 return true;
1152 }
1153 else
1154 {
1155 if((locTargetFirstPhi > locFirstSeedPhi) && (locTargetFirstPhi < locLastSeedPhi))
1156 return true;
1157 else if((locTargetLastPhi > locFirstSeedPhi) && (locTargetLastPhi < locLastSeedPhi))
1158 return true;
1159 else if((locFirstSeedPhi > locTargetFirstPhi) && (locFirstSeedPhi < locTargetLastPhi))
1160 return true;
1161 }
1162 }
1163 return false;
1164}
1165
1166/*********************************************************************************************************************************************************************/
1167/********************************************************************** SEARCH FOR SPIRAL LINKS **********************************************************************/
1168/*********************************************************************************************************************************************************************/
1169
1170//---------------------
1171// Set_SpiralLinkParams
1172//---------------------
1173void DTrackCandidate_factory_CDC::Set_SpiralLinkParams(void)
1174{
1175 // Search for Spiral Links within and between super layer seeds
1176 //don't worry about getting every case: it's better to have extra particles reconstructed than to be overzealous and lose some!!
1177 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds.size(); ++loc_i)
1178 {
1179 deque<DCDCSuperLayerSeed*>& locSuperLayerSeeds = dSuperLayerSeeds[loc_i];
1180 for(size_t loc_j = 0; loc_j < locSuperLayerSeeds.size(); ++loc_j)
1181 {
1182 for(size_t loc_k = loc_j + 1; loc_k < locSuperLayerSeeds.size(); ++loc_k)
1183 {
1184 if(SearchFor_SpiralTurn_TwoSeedsSharingManyHits(locSuperLayerSeeds[loc_j], locSuperLayerSeeds[loc_k]))
1185 continue;
1186 if(SearchFor_SpiralTurn_TwoSeedsSharingFewHits(locSuperLayerSeeds[loc_j], locSuperLayerSeeds[loc_k]))
1187 continue;
1188 if(SearchFor_SpiralTurn_MissingOrBetweenRings(locSuperLayerSeeds[loc_j], locSuperLayerSeeds[loc_k]))
1189 continue;
1190 }
1191 // if this super layer seed has not yet been linked to any other seed, check to see if itself is the spiral turn
1192 // e.g. only (and many) hits in one ring of super-layer 7.
1193 if(locSuperLayerSeeds[loc_j]->dSpiralLinkParams.empty()) //empty if not identified as a spiral yet
1194 SearchFor_SpiralTurn_SingleSeed(locSuperLayerSeeds[loc_j]);
1195 }
1196 }
1197}
1198
1199//---------------------------------------------
1200// SearchFor_SpiralTurn_TwoSeedsSharingManyHits
1201//---------------------------------------------
1202bool DTrackCandidate_factory_CDC::SearchFor_SpiralTurn_TwoSeedsSharingManyHits(DCDCSuperLayerSeed* locSuperLayerSeed1, DCDCSuperLayerSeed* locSuperLayerSeed2)
1203{
1204 //check if two seeds share at least MIN_STRAWS_POTENTIAL_SPIRAL_TURN on the same ring
1205
1206 int locMaxSpiralNumHits = 0; //can have more than one potential spiral turn on a seed: could have two tracks (or two spiral arms) turning near each other
1207 //search all rings: spiral turn may not be on outermost ring if two tracks are crossing
1208 for(size_t loc_i = 0; loc_i < locSuperLayerSeed1->dCDCRingSeeds.size(); ++loc_i)
1209 {
1210 int locRing = locSuperLayerSeed1->dCDCRingSeeds[loc_i].ring;
1211 if(!locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locRing))
1212 continue; //the hits on this ring aren't the same in both DCDCSuperLayerSeed's
1213 int locLocalRingNumber = (locRing - 1)%4 + 1; //ranges from 1 -> 4 //ring of super layer
1214
1215 // find how many straws are in this ring
1216 int locNumHits = locSuperLayerSeed1->dCDCRingSeeds[loc_i].hits.size();
1217 if(locNumHits < locMaxSpiralNumHits)
1218 continue; //already found a potential spiral link in this seed with a > # of straws
1219
1220 if(locNumHits >= int(MIN_STRAWS_POTENTIAL_SPIRAL_TURN))
1221 {
1222 // check to make sure the hits on the first and last rings (in this super layer) of both DCDCSuperLayerSeed's aren't identical
1223 //if so, then if there truly is a spiral, this is the wrong combination of DCDCSuperLayerSeed's for it
1224 int locFirstRing1 = locSuperLayerSeed1->dCDCRingSeeds.front().ring;
1225 int locFirstRing2 = locSuperLayerSeed2->dCDCRingSeeds.front().ring;
1226 int locLastRing1 = locSuperLayerSeed1->dCDCRingSeeds.back().ring;
1227 int locLastRing2 = locSuperLayerSeed2->dCDCRingSeeds.back().ring;
1228 if((locFirstRing1 == locFirstRing2) && (locLastRing1 == locLastRing2))
1229 {
1230 if(locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locFirstRing1) && locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locLastRing1))
1231 continue;
1232 }
1233
1234 int locTempSpiralNumHits = 0;
1235 if((locLocalRingNumber != 1) && (locLocalRingNumber != 4))
1236 {
1237 //spiral turn is not on an edge ring, it is on one of the two middle rings instead: there must also be MIN_STRAWS_ADJACENT_TO_SPIRAL_TURN hits in an adjacent ring
1238 //if spiral turn was on an edge ring, there may be many hits in the adjacent ring that is in another super layer, so can't do this check
1239 if(!SearchFor_SpiralTurn_ManyHitsAdjacentRing(locSuperLayerSeed1, locSuperLayerSeed2, locRing + 1, MIN_STRAWS_ADJACENT_TO_SPIRAL_TURN, locTempSpiralNumHits))
1240 {
1241 if(!SearchFor_SpiralTurn_ManyHitsAdjacentRing(locSuperLayerSeed1, locSuperLayerSeed2, locRing - 1, MIN_STRAWS_ADJACENT_TO_SPIRAL_TURN, locTempSpiralNumHits))
1242 continue; //not a spiral turn: there was only a few straws on the adjacent rings //perhaps this was two nearby tracks instead
1243 }
1244 }
1245
1246 // is potential spiral turn, save results
1247 locMaxSpiralNumHits = locNumHits;
1248 DSpiralParams_t locSpiralTurnParams;
1249 //try to determine whether the track is turning inwards or outwards in this ring
1250 int locSpiralTurnRingFlag = 0;
1251 if(locSuperLayerSeed1->dCDCRingSeeds.size() == 1)
1252 locSpiralTurnRingFlag = ((locRing - 1)%4 > 1) ? 1 : -1;
1253 else if(loc_i == 0)
1254 locSpiralTurnRingFlag = -1; //turn on innermost ring
1255 else if(loc_i == (locSuperLayerSeed1->dCDCRingSeeds.size() - 1))
1256 locSpiralTurnRingFlag = 1; //turn on outermost ring
1257 else if(locSuperLayerSeed1->dCDCRingSeeds[loc_i + 1].hits.size() > locSuperLayerSeed1->dCDCRingSeeds[loc_i - 1].hits.size())
1258 locSpiralTurnRingFlag = -1; //more hits on outer ring than inner ring: turn on innermost ring
1259 else
1260 locSpiralTurnRingFlag = 1; //turn on outermost ring (if hit vector sizes are equal, assume outermost)
1261 locSpiralTurnParams.dSpiralTurnRingFlag = locSpiralTurnRingFlag;
1262 locSpiralTurnParams.dSpiralTurnRing = locRing;
1263 locSpiralTurnParams.dDefiniteSpiralTurnRingFlag = (locNumHits >= int(MIN_STRAWS_DEFINITE_SPIRAL_TURN)) ? locSpiralTurnRingFlag : 0;
1264 locSuperLayerSeed1->dSpiralLinkParams[locSuperLayerSeed2->dSeedIndex] = locSpiralTurnParams;
1265 locSuperLayerSeed2->dSpiralLinkParams[locSuperLayerSeed1->dSeedIndex] = locSpiralTurnParams;
1266 if(DEBUG_LEVEL > 10)
1267 cout << "SL" << locSuperLayerSeed1->dSuperLayer << " Seed" << locSuperLayerSeed1->dSeedIndex << " Spiral-linked to SL" << locSuperLayerSeed2->dSuperLayer << " Seed" << locSuperLayerSeed2->dSeedIndex << ": Share Many Hits, Ring = " << locRing << endl;
1268 }
1269 }
1270 return (locMaxSpiralNumHits > 0);
1271}
1272
1273//--------------------------------------------
1274// SearchFor_SpiralTurn_TwoSeedsSharingFewHits
1275//--------------------------------------------
1276bool DTrackCandidate_factory_CDC::SearchFor_SpiralTurn_TwoSeedsSharingFewHits(DCDCSuperLayerSeed* locSuperLayerSeed1, DCDCSuperLayerSeed* locSuperLayerSeed2)
1277{
1278 // check if: two seeds share a few hits on a given ring, and at least one has very many (unshared) hits on an adjacent ring: spiral turn
1279
1280 int locMaxSpiralNumHits = 0; //can have more than one potential spiral turn on a seed: could have two tracks (or two spiral arms) turning near each other
1281 for(size_t loc_i = 0; loc_i < locSuperLayerSeed1->dCDCRingSeeds.size(); ++loc_i)
1282 {
1283 int locRing = locSuperLayerSeed1->dCDCRingSeeds[loc_i].ring;
1284 if(!locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locRing))
1285 continue;
1286
1287 //check locRing - 1 for many hits: check if track is turning back inwards
1288 int locTempSpiralNumHits = -2;
1289 if(SearchFor_SpiralTurn_ManyHitsAdjacentRing(locSuperLayerSeed1, locSuperLayerSeed2, locRing - 1, MIN_STRAWS_POTENTIAL_SPIRAL_TURN, locTempSpiralNumHits))
1290 {
1291 //is potential spiral turn
1292 if(locTempSpiralNumHits > locMaxSpiralNumHits)
1293 {
1294 locMaxSpiralNumHits = locTempSpiralNumHits;
1295 DSpiralParams_t locSpiralTurnParams;
1296 int locSpiralTurnRingFlag = 1; //turning inwards
1297 locSpiralTurnParams.dSpiralTurnRingFlag = locSpiralTurnRingFlag;
1298 locSpiralTurnParams.dSpiralTurnRing = locRing;
1299 bool locIsDefiniteSpiralTurn = (locTempSpiralNumHits > int(MIN_STRAWS_DEFINITE_SPIRAL_TURN));
1300 locSpiralTurnParams.dDefiniteSpiralTurnRingFlag = locIsDefiniteSpiralTurn ? locSpiralTurnRingFlag : 0;
1301 locSuperLayerSeed1->dSpiralLinkParams[locSuperLayerSeed2->dSeedIndex] = locSpiralTurnParams;
1302 locSuperLayerSeed2->dSpiralLinkParams[locSuperLayerSeed1->dSeedIndex] = locSpiralTurnParams;
1303 if(DEBUG_LEVEL > 10)
1304 cout << "SL" << locSuperLayerSeed1->dSuperLayer << " Seed" << locSuperLayerSeed1->dSeedIndex << " Spiral-linked to SL" << locSuperLayerSeed2->dSuperLayer << " Seed" << locSuperLayerSeed2->dSeedIndex << ": Share Few Hits, Ring = " << locRing << endl;
1305 }
1306 }
1307
1308 //check locRing + 1 for many hits: check if track is turning back outwards
1309 locTempSpiralNumHits = -2;
1310 if(SearchFor_SpiralTurn_ManyHitsAdjacentRing(locSuperLayerSeed1, locSuperLayerSeed2, locRing + 1, MIN_STRAWS_POTENTIAL_SPIRAL_TURN, locTempSpiralNumHits))
1311 {
1312 //is potential spiral turn
1313 if(locTempSpiralNumHits > locMaxSpiralNumHits)
1314 {
1315 locMaxSpiralNumHits = locTempSpiralNumHits;
1316 DSpiralParams_t locSpiralTurnParams;
1317 int locSpiralTurnRingFlag = -1; //turning outwards
1318 locSpiralTurnParams.dSpiralTurnRingFlag = locSpiralTurnRingFlag;
1319 locSpiralTurnParams.dSpiralTurnRing = locRing;
1320 bool locIsDefiniteSpiralTurn = (locTempSpiralNumHits > int(MIN_STRAWS_DEFINITE_SPIRAL_TURN));
1321 locSpiralTurnParams.dDefiniteSpiralTurnRingFlag = locIsDefiniteSpiralTurn ? locSpiralTurnRingFlag : 0;
1322 locSuperLayerSeed1->dSpiralLinkParams[locSuperLayerSeed2->dSeedIndex] = locSpiralTurnParams;
1323 locSuperLayerSeed2->dSpiralLinkParams[locSuperLayerSeed1->dSeedIndex] = locSpiralTurnParams;
1324 if(DEBUG_LEVEL > 10)
1325 cout << "SL" << locSuperLayerSeed1->dSuperLayer << " Seed" << locSuperLayerSeed1->dSeedIndex << " Spiral-linked to SL" << locSuperLayerSeed2->dSuperLayer << " Seed" << locSuperLayerSeed2->dSeedIndex << ": Share Few Hits, Ring = " << locRing << endl;
1326 }
1327 }
1328 }
1329
1330 return (locMaxSpiralNumHits > 0);
1331}
1332
1333//------------------------------------------
1334// SearchFor_SpiralTurn_ManyHitsAdjacentRing
1335//------------------------------------------
1336bool DTrackCandidate_factory_CDC::SearchFor_SpiralTurn_ManyHitsAdjacentRing(DCDCSuperLayerSeed* locSuperLayerSeed1, DCDCSuperLayerSeed* locSuperLayerSeed2, int locRingToCheck, int locMinStrawsAdjacentRing, int& locMaxSpiralNumHits)
1337{
1338 //utility function, used to confirm if there are many hits on both seeds in the given ring
1339 if(locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locRingToCheck))
1340 return false; //these hits are the same
1341
1342 deque<DCDCTrkHit*> locHits1;
1343 for(size_t loc_i = 0; loc_i < locSuperLayerSeed1->dCDCRingSeeds.size(); ++loc_i)
1344 {
1345 if(locSuperLayerSeed1->dCDCRingSeeds[loc_i].ring != locRingToCheck)
1346 continue;
1347 locHits1 = locSuperLayerSeed1->dCDCRingSeeds[loc_i].hits;
1348 break;
1349 }
1350 if(locHits1.empty())
1351 return false;
1352
1353 deque<DCDCTrkHit*> locHits2;
1354 for(size_t loc_j = 0; loc_j < locSuperLayerSeed2->dCDCRingSeeds.size(); ++loc_j)
1355 {
1356 if(locSuperLayerSeed2->dCDCRingSeeds[loc_j].ring != locRingToCheck)
1357 continue;
1358 locHits2 = locSuperLayerSeed2->dCDCRingSeeds[loc_j].hits;
1359 break;
1360 }
1361 if(locHits2.empty())
1362 return false;
1363
1364 int locNumHits1 = locHits1.size();
1365 int locNumHits2 = locHits2.size();
1366
1367 if((locNumHits1 < int(locMinStrawsAdjacentRing)) || (locNumHits2 < int(locMinStrawsAdjacentRing)))
1368 return false; //neither seed has enough hits on the adjacent ring: return false
1369
1370 // check to make sure the hits on the inner & outer rings of both seeds aren't identical
1371 //if there truly is a spiral, then this is the wrong combo of seeds for it
1372 int locFirstRing1 = locSuperLayerSeed1->dCDCRingSeeds.front().ring;
1373 int locFirstRing2 = locSuperLayerSeed2->dCDCRingSeeds.front().ring;
1374 int locLastRing1 = locSuperLayerSeed1->dCDCRingSeeds.back().ring;
1375 int locLastRing2 = locSuperLayerSeed2->dCDCRingSeeds.back().ring;
1376 if((locFirstRing1 == locFirstRing2) && (locLastRing1 == locLastRing2))
1377 {
1378 if(locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locFirstRing1) && locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locLastRing1))
1379 return false;
1380 }
1381
1382 locMaxSpiralNumHits = locNumHits1;
1383 if(locNumHits2 > locMaxSpiralNumHits)
1384 locMaxSpiralNumHits = locNumHits2;
1385
1386 return true;
1387}
1388
1389//-------------------------------------------
1390// SearchFor_SpiralTurn_MissingOrBetweenRings
1391//-------------------------------------------
1392bool DTrackCandidate_factory_CDC::SearchFor_SpiralTurn_MissingOrBetweenRings(DCDCSuperLayerSeed* locSuperLayerSeed1, DCDCSuperLayerSeed* locSuperLayerSeed2)
1393{
1394 // sometimes the spiral turn occurs between rings (or in a region with a dead high-voltage board). this function attempts to find these
1395 // the signature is that both seeds have many hits in a given ring. these hits must be different but nearby, and the majority of the hits in the other rings must be further away from the other seed
1396 int locMaxSpiralNumHits = 0; //can have more than one potential spiral turn on a seed: could have two tracks (or two spiral arms) turning near each other
1397 for(size_t loc_i = 0; loc_i < locSuperLayerSeed1->dCDCRingSeeds.size(); ++loc_i)
1398 {
1399 int locRing = locSuperLayerSeed1->dCDCRingSeeds[loc_i].ring;
1400
1401 //make sure there are enough straws on this ring in seed1
1402 deque<DCDCTrkHit*>& locHits1 = locSuperLayerSeed1->dCDCRingSeeds[loc_i].hits;
1403 int locNumHits1 = locHits1.size();
1404 if(locNumHits1 < int(MIN_STRAWS_POTENTIAL_SPIRAL_TURN))
1405 continue; //not enough straws
1406
1407 for(size_t loc_j = 0; loc_j < locSuperLayerSeed2->dCDCRingSeeds.size(); ++loc_j)
1408 {
1409 if(locSuperLayerSeed2->dCDCRingSeeds[loc_j].ring != locRing)
1410 continue; //select the same ring as in seed1
1411
1412 deque<DCDCTrkHit*>& locHits2 = locSuperLayerSeed2->dCDCRingSeeds[loc_j].hits;
1413 if(locHits2 == locHits1)
1414 break; //hits are shared: if truly was a spiral, will have been picked up earlier
1415
1416 //make sure there are enough straws on this ring in seed2
1417 int locNumHits2 = locHits2.size();
1418 if(locNumHits2 < int(MIN_STRAWS_POTENTIAL_SPIRAL_TURN))
1419 break; //not enough straws
1420
1421 bool locAtLeastOneSeedDefiniteTurnFlag = (locNumHits1 >= int(MIN_STRAWS_DEFINITE_SPIRAL_TURN));
1422 if(locNumHits2 >= int(MIN_STRAWS_DEFINITE_SPIRAL_TURN))
1423 locAtLeastOneSeedDefiniteTurnFlag = true;
1424
1425 //check to make sure the seeds are nearby
1426 int locStrawNumDiff = abs(locHits2.front()->hit->wire->straw - locHits1.back()->hit->wire->straw);
1427 int locNumStrawsInRing = dNumStrawsPerRing[locRing - 1];
1428 if(locStrawNumDiff > locNumStrawsInRing/2)
1429 locStrawNumDiff = locNumStrawsInRing - locStrawNumDiff; //crosses straw count edge
1430 int locNumHits = locStrawNumDiff - 1;
1431 if(locNumHits > int(MAX_STRAWS_BETWEEN_LINK_SPIRAL_TURN))
1432 break; //straw groups are too far apart
1433
1434 // check to make sure the hits on the inner & outer rings of both seeds aren't identical
1435 //if there truly is a spiral, then this is the wrong combo of seeds for it
1436 int locFirstRing1 = locSuperLayerSeed1->dCDCRingSeeds.front().ring;
1437 int locFirstRing2 = locSuperLayerSeed2->dCDCRingSeeds.front().ring;
1438 int locLastRing1 = locSuperLayerSeed1->dCDCRingSeeds.back().ring;
1439 int locLastRing2 = locSuperLayerSeed2->dCDCRingSeeds.back().ring;
1440 if((locFirstRing1 == locFirstRing2) && (locLastRing1 == locLastRing2))
1441 {
1442 if(locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locFirstRing1) && locSuperLayerSeed1->Are_AllHitsOnRingShared(locSuperLayerSeed2, locLastRing1))
1443 continue;
1444 }
1445
1446 if((locNumHits1 < locMaxSpiralNumHits) && (locNumHits2 < locMaxSpiralNumHits))
1447 continue; //a seed with more hits was found earlier
1448 if(locNumHits1 > locMaxSpiralNumHits)
1449 locMaxSpiralNumHits = locNumHits1;
1450 if(locNumHits2 > locMaxSpiralNumHits)
1451 locMaxSpiralNumHits = locNumHits2;
1452
1453 //will use results from circle fits to make sure the seeds are turning in the correct direction.
1454 DSpiralParams_t locSpiralTurnParams;
1455 // try to determine if the spiral is turning inwards or outwards
1456 int locSpiralTurnRingFlag = 0;
1457 if(locSuperLayerSeed1->dCDCRingSeeds.size() == 1)
1458 locSpiralTurnRingFlag = ((locRing - 1)%4 > 1) ? 1 : -1;
1459 else if(loc_i == 0)
1460 locSpiralTurnRingFlag = -1; //turn on innermost ring
1461 else if(loc_i == (locSuperLayerSeed1->dCDCRingSeeds.size() - 1))
1462 locSpiralTurnRingFlag = 1; //turn on outermost ring
1463 else if(locSuperLayerSeed1->dCDCRingSeeds[loc_i + 1].hits.size() > locSuperLayerSeed1->dCDCRingSeeds[loc_i - 1].hits.size())
1464 locSpiralTurnRingFlag = -1; //more hits on outer ring than inner ring: turn on innermost ring
1465 else
1466 locSpiralTurnRingFlag = 1; //turn on outermost ring (if hit vector sizes are equal, assume outermost)
1467 locSpiralTurnParams.dSpiralTurnRingFlag = locSpiralTurnRingFlag;
1468 locSpiralTurnParams.dSpiralTurnRing = locRing;
1469 locSpiralTurnParams.dDefiniteSpiralTurnRingFlag = locAtLeastOneSeedDefiniteTurnFlag ? locSpiralTurnRingFlag : 0;
1470 locSuperLayerSeed1->dSpiralLinkParams[locSuperLayerSeed2->dSeedIndex] = locSpiralTurnParams;
1471 locSuperLayerSeed2->dSpiralLinkParams[locSuperLayerSeed1->dSeedIndex] = locSpiralTurnParams;
1472
1473 if(DEBUG_LEVEL > 10)
1474 cout << "SL" << locSuperLayerSeed1->dSuperLayer << " Seed" << locSuperLayerSeed1->dSeedIndex << " Spiral-linked to SL" << locSuperLayerSeed2->dSuperLayer << " Seed" << locSuperLayerSeed2->dSeedIndex << ": Share No Hits, Ring = " << locRing << endl;
1475 }
1476 }
1477
1478 return (locMaxSpiralNumHits > 0);
1479}
1480
1481//--------------------------------
1482// SearchFor_SpiralTurn_SingleSeed
1483//--------------------------------
1484bool DTrackCandidate_factory_CDC::SearchFor_SpiralTurn_SingleSeed(DCDCSuperLayerSeed* locSuperLayerSeed)
1485{
1486 // search for a spiral turn contained within this DCDCSuperLayerSeed
1487 // signature is a ring with many hits
1488 int locMaxSpiralNumHits = 0; //can have more than one potential spiral turn on a seed: could have two tracks (or two spiral arms) turning near each other
1489 for(size_t loc_i = 0; loc_i < locSuperLayerSeed->dCDCRingSeeds.size(); ++loc_i)
1490 {
1491 int locRing = locSuperLayerSeed->dCDCRingSeeds[loc_i].ring;
1492 int locNumHits = locSuperLayerSeed->dCDCRingSeeds[loc_i].hits.size();
1493 if(locNumHits < locMaxSpiralNumHits)
1494 continue; //already found a potential spiral link in this seed with a > # of straws
1495
1496 if(locNumHits < int(MIN_STRAWS_POTENTIAL_SPIRAL_TURN))
1497 continue; //not enough straws in seed
1498 locMaxSpiralNumHits = locNumHits;
1499
1500 DSpiralParams_t locSpiralTurnParams;
1501 int locSpiralTurnRingFlag = ((locRing - 1)%4 > 1) ? 1 : -1;
1502 locSpiralTurnParams.dSpiralTurnRingFlag = locSpiralTurnRingFlag;
1503 locSpiralTurnParams.dSpiralTurnRing = locRing;
1504 locSpiralTurnParams.dDefiniteSpiralTurnRingFlag = (locNumHits >= int(MIN_STRAWS_DEFINITE_SPIRAL_TURN)) ? locSpiralTurnRingFlag : 0;
1505 locSuperLayerSeed->dSpiralLinkParams[locSuperLayerSeed->dSeedIndex] = locSpiralTurnParams;
1506 if(DEBUG_LEVEL > 10)
1507 cout << "SL" << locSuperLayerSeed->dSuperLayer << " Seed" << locSuperLayerSeed->dSeedIndex << " Self-spiral-linked: Ring = " << locRing << endl;
1508 }
1509 return (locMaxSpiralNumHits > 0);
1510}
1511
1512//----------------------
1513// Print_SuperLayerSeeds
1514//----------------------
1515void DTrackCandidate_factory_CDC::Print_SuperLayerSeeds(void)
1516{
1517 cout << "HITS BY SUPER LAYER & SEED INDEX:" << endl;
1518 for(unsigned int loc_i = 0; loc_i < 7; ++loc_i)
1519 {
1520 cout << " SUPER LAYER " << loc_i + 1 << ":" << endl;
1521 for(unsigned int loc_j = 0; loc_j < dSuperLayerSeeds[loc_i].size(); ++loc_j)
1522 {
1523 cout << " Seed Index " << loc_j << ":" << endl;
1524 DCDCSuperLayerSeed* locSuperLayerSeed = dSuperLayerSeeds[loc_i][loc_j];
1525 deque<DCDCTrkHit*> locHits;
1526 locSuperLayerSeed->Get_Hits(locHits);
1527 for(unsigned int loc_k = 0; loc_k < locHits.size(); ++loc_k)
1528 cout << "ring, straw, E (keV) = " << locHits[loc_k]->hit->wire->ring << ", " << locHits[loc_k]->hit->wire->straw << ", " << 1.0E6*locHits[loc_k]->hit->dE << endl;
1529 for(map<int, DSpiralParams_t>::iterator locIterator = locSuperLayerSeed->dSpiralLinkParams.begin(); locIterator != locSuperLayerSeed->dSpiralLinkParams.end(); ++locIterator)
1530 cout << "dSpiralLinkSeedIndex, dSpiralTurnRingFlag, dSpiralTurnRing, dDefiniteSpiralTurnRingFlag = " << locIterator->first << ", " << locIterator->second.dSpiralTurnRingFlag << ", " << locIterator->second.dSpiralTurnRing << ", " << locIterator->second.dDefiniteSpiralTurnRingFlag << endl;
1531 }
1532 }
1533}
1534
1535/*********************************************************************************************************************************************************************/
1536/************************************************************************ Build Track Circles ************************************************************************/
1537/*********************************************************************************************************************************************************************/
1538
1539//-------------------
1540// Build_TrackCircles
1541//-------------------
1542bool DTrackCandidate_factory_CDC::Build_TrackCircles(deque<DCDCTrackCircle*>& locCDCTrackCircles)
1543{
1544 //return false if had to bail due to failure (i.e. too many track circles)
1545 //return true even if no track circles: it worked, it's just there aren't any
1546
1547 //link DCDCSuperLayers together to form track circles
1548 locCDCTrackCircles.clear();
1549 for(unsigned int locOuterSuperLayer = 2; locOuterSuperLayer <= 7; ++locOuterSuperLayer)
1550 {
1551 unsigned int locInnerSuperLayer = locOuterSuperLayer - 1;
1552 if(locCDCTrackCircles.empty())
1553 {
1554 // no track circles yet: create new track circle objects using the super layer seeds in locInnerSuperLayer
1555 if(locInnerSuperLayer > MAX_SUPERLAYER_NEW_TRACK)
1556 return true; // don't create track circles beyond super layer MAX_SUPERLAYER_NEW_TRACK (e.g. knockout electrons from BCAL), return: no track circles!!!
1557 if(dSuperLayerSeeds[locInnerSuperLayer - 1].empty())
1558 continue; // no inner seeds, try next super layer
1559 //build new DCDCTrackCircle's: one for each super layer seed in this (inner) super layer
1560 for(size_t loc_j = 0; loc_j < dSuperLayerSeeds[locInnerSuperLayer - 1].size(); ++loc_j)
1561 {
1562 DCDCSuperLayerSeed* locSuperLayerSeed = dSuperLayerSeeds[locInnerSuperLayer - 1][loc_j];
1563 DCDCTrackCircle* locCDCTrackCircle = Get_Resource_CDCTrackCircle();
1564 if((locInnerSuperLayer == 1) || (locInnerSuperLayer == 4) || (locInnerSuperLayer == 7))
1565 locCDCTrackCircle->dSuperLayerSeeds_Axial.push_back(locSuperLayerSeed);
1566 else if((locInnerSuperLayer == 2) || (locInnerSuperLayer == 3))
1567 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(deque<DCDCSuperLayerSeed*>(1, locSuperLayerSeed));
1568 else
1569 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(deque<DCDCSuperLayerSeed*>(1, locSuperLayerSeed));
1570 locCDCTrackCircles.push_back(locCDCTrackCircle);
1571 }
1572 }
1573 //link existing track circles to DCDCSuperLayerSeed's in the outer super layer. Any unused DCDCSuperLayerSeed's will be used to make new track circles
1574 if(!Link_SuperLayers(locCDCTrackCircles, locOuterSuperLayer))
1575 return false; //too many track circles
1576 }
1577 //if still no tracks, make DCDCSuperLayerSeed's in super layer 7 into new tracks (if allowed (probably shouldn't be))
1578 if(locCDCTrackCircles.empty() && (MAX_SUPERLAYER_NEW_TRACK >= 7))
1579 {
1580 for(size_t loc_j = 0; loc_j < dSuperLayerSeeds[6].size(); ++loc_j)
1581 {
1582 DCDCSuperLayerSeed* locSuperLayerSeed = dSuperLayerSeeds[6][loc_j];
1583 DCDCTrackCircle* locCDCTrackCircle = Get_Resource_CDCTrackCircle();
1584 locCDCTrackCircle->dSuperLayerSeeds_Axial.push_back(locSuperLayerSeed);
1585 locCDCTrackCircles.push_back(locCDCTrackCircle);
1586 }
1587 }
1588 if(locCDCTrackCircles.empty())
1589 return true;
1590
1591 //shouldn't be possible, but check to see if too many (should've failed sooner)
1592 if(locCDCTrackCircles.size() >= MAX_ALLOWED_TRACK_CIRCLES)
1593 {
1594 if(DEBUG_LEVEL > 10)
1595 cout << "Too many track circles; bailing" << endl;
1596 locCDCTrackCircles.clear();
1597 return true;
1598 }
1599
1600 // Reject track circles if they are definitely a spiral arm that turns back outwards in its inner super layer
1601 Reject_DefiniteSpiralArms(locCDCTrackCircles);
1602 if(locCDCTrackCircles.empty())
1603 return true;
1604
1605 // Reject track circles that don't contain at least one axial and one stereo super layer, unless that axial is super layer 1
1606 Drop_IncompleteGroups(locCDCTrackCircles);
1607 if(locCDCTrackCircles.empty())
1608 return true;
1609
1610 if(DEBUG_LEVEL > 5)
1611 {
1612 cout << "LINKED TRACK CIRCLES" << endl;
1613 Print_TrackCircles(locCDCTrackCircles);
1614 }
1615
1616 //fit circles to the DCDCTrackCircle's. This will reject fits if they aren't very good
1617 //1st false: fit all circles //2nd false: don't add intersections between stereo layers (wait until specific stereo super layers have been selected)
1618 Fit_Circles(locCDCTrackCircles, false, false);
1619 if(locCDCTrackCircles.empty())
1620 return true;
1621 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByChiSqPerNDFDecreasing); //sort by circle-fit weighted chisq/ndf (largest first)
1622
1623 if(DEBUG_LEVEL > 5)
1624 {
1625 cout << "post circle fit" << endl;
1626 Print_TrackCircles(locCDCTrackCircles);
1627 }
1628
1629 return true;
1630}
1631
1632//-----------------
1633// Link_SuperLayers
1634//-----------------
1635bool DTrackCandidate_factory_CDC::Link_SuperLayers(deque<DCDCTrackCircle*>& locCDCTrackCircles, unsigned int locOuterSuperLayer)
1636{
1637 /// Loop over the DCDCTrackCircles and the next super layer seeds and compare the positions of
1638 /// their first and last hits to see if we should link them together.
1639 /// If at <= MAX_SUPERLAYER_NEW_TRACK: Any seeds from the outer super layer that are not linked will be added to the <i>DCDCTrackCircle</i> list.
1640 /// Will try to link by skipping a super layer if a link was not previously performed and ENABLE_DEAD_HV_BOARD_LINKING is set to true (default false)
1641
1642 if(DEBUG_LEVEL > 3)
1643 cout << "Linking seeds, locOuterSuperLayer = " << locOuterSuperLayer << endl;
1644
1645 //Link locCDCTrackCircles's to the next super layer seeds
1646 unsigned int locInnerSuperLayer = locOuterSuperLayer - 1;
1647 if((locInnerSuperLayer == 1) || (locInnerSuperLayer == 4)) //else linking from stereo
1648 Link_SuperLayers_FromAxial(locCDCTrackCircles, locOuterSuperLayer, locInnerSuperLayer);
1649 else if((locOuterSuperLayer == 4) || (locOuterSuperLayer == 7))
1650 {
1651 if(!Link_SuperLayers_FromStereo_ToAxial(locCDCTrackCircles, locOuterSuperLayer, locInnerSuperLayer))
1652 return false; //linking failed: too many track circles
1653 }
1654 else
1655 Link_SuperLayers_FromStereo_ToStereo(locCDCTrackCircles, locOuterSuperLayer, locInnerSuperLayer);
1656 if(DEBUG_LEVEL > 25)
1657 {
1658 cout << "Link-to SL" << locOuterSuperLayer << ", v1" << endl;
1659 Print_TrackCircles(locCDCTrackCircles);
1660 }
1661
1662 //For DCDCTrackCircle's that failed to link, try checking to see if can link to the previous super layer (e.g. a HV board was dead)
1663 if(ENABLE_DEAD_HV_BOARD_LINKING && (locInnerSuperLayer != 1))
1664 {
1665 --locInnerSuperLayer;
1666 if(DEBUG_LEVEL > 3)
1667 cout << "Try to skip super layer (e.g. HV board dead); new inner super layer = " << locInnerSuperLayer << endl;
1668 if((locInnerSuperLayer == 1) || (locInnerSuperLayer == 4))
1669 Link_SuperLayers_FromAxial(locCDCTrackCircles, locOuterSuperLayer, locInnerSuperLayer);
1670 else if((locOuterSuperLayer == 4) || (locOuterSuperLayer == 7))
1671 {
1672 if(!Link_SuperLayers_FromStereo_ToAxial(locCDCTrackCircles, locOuterSuperLayer, locInnerSuperLayer))
1673 return false; //linking failed: too many track circles
1674 }
1675 else
1676 Link_SuperLayers_FromStereo_ToStereo(locCDCTrackCircles, locOuterSuperLayer, locInnerSuperLayer);
1677 if(DEBUG_LEVEL > 25)
1678 {
1679 cout << "Link-to SL" << locOuterSuperLayer << ", v2" << endl;
1680 Print_TrackCircles(locCDCTrackCircles);
1681 }
1682 }
1683
1684 // For outer seeds that failed to link, save as new track circles (even if they are stereo layers), UNLESS they are after MAX_SUPERLAYER_NEW_TRACK
1685 // UNLESS: a region at about the same phi in a previous super layer had a very high density of hits (such that all seeds in it were rejected)
1686 // Don't want to create new tracks in this case!
1687 if(locOuterSuperLayer <= MAX_SUPERLAYER_NEW_TRACK)
1688 {
1689 if(DEBUG_LEVEL > 3)
1690 cout << "Save any unlinked as new track circles" << endl;
1691 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds[locOuterSuperLayer - 1].size(); ++loc_i)
1692 {
1693 DCDCSuperLayerSeed* locSuperLayerSeed = dSuperLayerSeeds[locOuterSuperLayer - 1][loc_i];
1694 if(locSuperLayerSeed->linked)
1695 continue; //previously linked, don't create new object
1696 //make sure this seed doesn't correspond to a region in phi where all of the seeds were deleted earlier
1697 //calc phi range of seed
1698 double locSeedFirstPhi, locSeedLastPhi;
1699 Calc_SuperLayerPhiRange(locSuperLayerSeed, locSeedFirstPhi, locSeedLastPhi);
1700 bool locHitDensityPreviouslyTooHighFlag = false;
1701 for(size_t loc_j = 1; loc_j < locOuterSuperLayer; ++loc_j)
1702 {
1703 for(size_t loc_k = 0; loc_k < dRejectedPhiRegions[loc_j].size(); ++loc_k)
1704 {
1705 if(!Check_IfPhiRangesOverlap(locSeedFirstPhi, locSeedLastPhi, dRejectedPhiRegions[loc_j][loc_k].first, dRejectedPhiRegions[loc_j][loc_k].second))
1706 continue;
1707 locHitDensityPreviouslyTooHighFlag = true;
1708 break;
1709 }
1710 if(locHitDensityPreviouslyTooHighFlag)
1711 break;
1712 }
1713 if(locHitDensityPreviouslyTooHighFlag)
1714 continue;
1715 //create new track circle
1716 if(DEBUG_LEVEL > 10)
1717 cout << "Unlinked seed; create new track circle: super layer & seed index = " << locSuperLayerSeed->dSuperLayer << ", " << locSuperLayerSeed->dSeedIndex << endl;
1718 if(locCDCTrackCircles.size() >= MAX_ALLOWED_TRACK_CIRCLES)
1719 {
1720 if(DEBUG_LEVEL > 10)
1721 cout << "Too many track circles; bailing" << endl;
1722 locCDCTrackCircles.clear();
1723 return false;
1724 }
1725 DCDCTrackCircle* locCDCTrackCircle = Get_Resource_CDCTrackCircle();
1726 if((locOuterSuperLayer == 4) || (locOuterSuperLayer == 7))
1727 locCDCTrackCircle->dSuperLayerSeeds_Axial.push_back(locSuperLayerSeed);
1728 else if((locOuterSuperLayer == 2) || (locOuterSuperLayer == 3))
1729 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(deque<DCDCSuperLayerSeed*>(1, locSuperLayerSeed));
1730 else
1731 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(deque<DCDCSuperLayerSeed*>(1, locSuperLayerSeed));
1732 locCDCTrackCircles.push_back(locCDCTrackCircle);
1733 }
1734 if(DEBUG_LEVEL > 25)
1735 {
1736 cout << "Link-to SL" << locOuterSuperLayer << ", v3" << endl;
1737 Print_TrackCircles(locCDCTrackCircles);
1738 }
1739 }
1740
1741 return true;
1742}
1743
1744//---------------------------
1745// Link_SuperLayers_FromAxial
1746//---------------------------
1747void DTrackCandidate_factory_CDC::Link_SuperLayers_FromAxial(deque<DCDCTrackCircle*>& locCDCTrackCircles, unsigned int locOuterSuperLayer, unsigned int locInnerSuperLayer)
1748{
1749 //Link locCDCTrackCircles from an axial super layer to a stereo super layer (must be stereo: cannot skip two (both stereo) super layers)
1750 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
1751 {
1752 DCDCTrackCircle* locCDCTrackCircle = locCDCTrackCircles[loc_i];
1753 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
1754 continue; // no axial super layer seeds to link from
1755 DCDCSuperLayerSeed* locSuperLayerSeed1 = locCDCTrackCircle->dSuperLayerSeeds_Axial.back();
1756 if(locSuperLayerSeed1->dSuperLayer != locInnerSuperLayer)
1757 continue; // e.g. the track ended earlier
1758 if(DEBUG_LEVEL > 10)
1759 cout << "Seed 1 Super Layer, Seed Index = " << locSuperLayerSeed1->dSuperLayer << ", " << locSuperLayerSeed1->dSeedIndex << endl;
1760 if(!Check_IfShouldAttemptLink(locSuperLayerSeed1, true))
1761 continue; //don't attempt seed link if the inner seed was a definite spiral turn that was turning back inwards, etc.
1762
1763 // if trying to skip a layer, first check to make sure this seed wasn't already linked (to layer "locInnerSuperLayer + 1")
1764 if((locInnerSuperLayer == 1) && (!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty()))
1765 continue; //already linked to some inner stereo seeds
1766 else if((locInnerSuperLayer == 4) && (!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty()))
1767 continue; //already linked to some outer stereo seeds
1768
1769 for(size_t loc_j = 0; loc_j < dSuperLayerSeeds[locOuterSuperLayer - 1].size(); ++loc_j)
1770 {
1771 DCDCSuperLayerSeed* locSuperLayerSeed2 = dSuperLayerSeeds[locOuterSuperLayer - 1][loc_j];
1772 if(DEBUG_LEVEL > 10)
1773 cout << "Seed 2 Super Layer, Seed Index = " << locSuperLayerSeed2->dSuperLayer << ", " << locSuperLayerSeed2->dSeedIndex << endl;
1774 if(!Check_IfShouldAttemptLink(locSuperLayerSeed2, false))
1775 continue; //don't attempt seed link if the outer seed was a definite spiral turn that was turning back outwards, etc.
1776 if(DEBUG_LEVEL > 10)
1777 cout << "Attempting Seed Link" << endl;
1778 if(!Attempt_SeedLink(locSuperLayerSeed1, locSuperLayerSeed2)) //see if seeds are nearby enough to link
1779 continue;
1780 //LINK SUCCESSFUL!!
1781 if(DEBUG_LEVEL > 10)
1782 cout << "LINK SUCCESSFUL" << endl;
1783 locSuperLayerSeed1->linked = true;
1784 locSuperLayerSeed2->linked = true;
1785
1786 //create new group of stereo seeds (assumes linking to stereo: cannot axial (would skip too many))
1787 if(locOuterSuperLayer < 4)
1788 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(deque<DCDCSuperLayerSeed*>(1, locSuperLayerSeed2));
1789 else
1790 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(deque<DCDCSuperLayerSeed*>(1, locSuperLayerSeed2));
1791 }
1792 }
1793}
1794
1795//------------------------------------
1796// Link_SuperLayers_FromStereo_ToAxial
1797//------------------------------------
1798bool DTrackCandidate_factory_CDC::Link_SuperLayers_FromStereo_ToAxial(deque<DCDCTrackCircle*>& locCDCTrackCircles, unsigned int locOuterSuperLayer, unsigned int locInnerSuperLayer)
1799{
1800 // Link from a stereo super layer to an axial super layer. Unfortunately, this is extremely messy.
1801 //If you're editing this, I stronly suggest reading the simpler Link_SuperLayers_FromStereo_ToStereo function to make sure you understand it first. Good luck! :)
1802
1803 //since linking to axial, will create new track circles (one for each unique combo of axial seeds)
1804 deque<DCDCTrackCircle*> locNewCDCTrackCircles; //will eventually return this deque (by setting locCDCTrackCircles to it at the end)
1805
1806 // first save all track circles for output (into locNewCDCTrackCircles) that definitely will NOT be linked from:
1807 //those that already have an axial layer greater than the stereo we're linking from
1808 //this happens when trying to skip a super layer (e.g. a dead hv board), but this circle link was linked successfully
1809 //do this first, so that if an axial combo is created later that somehow is identical (e.g. due to skipping a super layer due to a dead HV board)
1810 //the stereo seeds will just be merged with the already existing one
1811 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
1812 {
1813 DCDCTrackCircle* locCDCTrackCircle = locCDCTrackCircles[loc_i];
1814 if(!locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
1815 {
1816 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.back()->dSuperLayer > locInnerSuperLayer)
1817 {
1818 locNewCDCTrackCircles.push_back(locCDCTrackCircle);
1819 continue;
1820 }
1821 }
1822 }
1823
1824 // loop over track circles
1825 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
1826 {
1827 DCDCTrackCircle* locCDCTrackCircle = locCDCTrackCircles[loc_i];
1828
1829 // if trying to skip a layer, first check to make sure this seed wasn't already linked (to layer "locInnerSuperLayer + 1")
1830 // axial checked here, stereo checked for each stereo series below
1831 if(!locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
1832 {
1833 // circle already saved in the output (above), so just skip linking here
1834 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.back()->dSuperLayer > locInnerSuperLayer)
1835 continue;
1836 }
1837
1838 // determine if linking from the stereo seeds stored in the dSuperLayerSeeds_InnerStereo or dSuperLayerSeeds_OuterStereo deques
1839 bool locFromInnerStereoFlag = (locInnerSuperLayer < 4);
1840 if(!locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
1841 {
1842 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.back()->dSuperLayer != 4)
1843 locFromInnerStereoFlag = true; //middle axial layer is missing, store stereo layer as inner
1844 }
1845
1846 //get a deque containing all of the series's of seeds to loop over
1847 deque<deque<DCDCSuperLayerSeed*> > locPreLinkedCDCSuperLayerSeeds;
1848 if(locFromInnerStereoFlag) //if on outer stereo seeds but axial seed 4 is missing, use inner stereo seeds
1849 locPreLinkedCDCSuperLayerSeeds = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo;
1850 else //use outer stereo seeds
1851 locPreLinkedCDCSuperLayerSeeds = locCDCTrackCircle->dSuperLayerSeeds_OuterStereo; //for looping over
1852
1853 bool locTrackCircleSavedFlag = false; //make sure that this track circle is saved in the output even if no future link is found
1854 //loop over each series of stereo seeds
1855 for(size_t loc_j = 0; loc_j < locPreLinkedCDCSuperLayerSeeds.size(); ++loc_j)
1856 {
1857 //get the last DCDCSuperLayerSeed in this stereo seed series
1858 deque<DCDCSuperLayerSeed*> locStereoSeedSeries = locPreLinkedCDCSuperLayerSeeds[loc_j];
1859 DCDCSuperLayerSeed* locSuperLayerSeed1 = locPreLinkedCDCSuperLayerSeeds[loc_j].back();
1860 if(DEBUG_LEVEL > 10)
1861 cout << "Seed 1 Super Layer, Seed Index = " << locSuperLayerSeed1->dSuperLayer << ", " << locSuperLayerSeed1->dSeedIndex << endl;
1862
1863 bool locInnerSeedLinkSuccessfulFlag = false;
1864 //don't attempt seed link if wrong super layer, or if the inner seed was a definite spiral turn that was turning back inwards, etc.
1865 if((locSuperLayerSeed1->dSuperLayer == locInnerSuperLayer) && Check_IfShouldAttemptLink(locSuperLayerSeed1, true))
1866 {
1867 //attempt to link to the outer superlayer
1868 for(size_t loc_k = 0; loc_k < dSuperLayerSeeds[locOuterSuperLayer - 1].size(); ++loc_k)
1869 {
1870 DCDCSuperLayerSeed* locSuperLayerSeed2 = dSuperLayerSeeds[locOuterSuperLayer - 1][loc_k];
1871 if(DEBUG_LEVEL > 10)
1872 cout << "Seed 2 Super Layer, Seed Index = " << locSuperLayerSeed2->dSuperLayer << ", " << locSuperLayerSeed2->dSeedIndex << endl;
1873 if(!Check_IfShouldAttemptLink(locSuperLayerSeed2, false))
1874 continue; //don't attempt seed link if the outer seed was a definite spiral turn that was turning back outwards, etc.
1875 if(DEBUG_LEVEL > 10)
1876 cout << "Attempting Seed Link" << endl;
1877 if(!Attempt_SeedLink(locSuperLayerSeed1, locSuperLayerSeed2)) //see if seeds are nearby enough to link
1878 continue;
1879 //LINK SUCCESSFUL!!
1880 if(DEBUG_LEVEL > 10)
1881 cout << "LINK SUCCESSFUL" << endl;
1882 locSuperLayerSeed1->linked = true;
1883 locSuperLayerSeed2->linked = true;
1884 locInnerSeedLinkSuccessfulFlag = true;
1885
1886 //make new deque of axial seeds
1887 deque<DCDCSuperLayerSeed*> locNewCDCSuperLayerSeeds_Axial = locCDCTrackCircle->dSuperLayerSeeds_Axial;
1888 locNewCDCSuperLayerSeeds_Axial.push_back(locSuperLayerSeed2);
1889
1890 //see if should create new DCDCTrackCircle object (axial combo is unique) or use a (probably recently created) existing one (it is not unique)
1891 DCDCTrackCircle* locNewCDCTrackCircle = NULL__null;
1892 for(size_t loc_l = 0; loc_l < locNewCDCTrackCircles.size(); ++loc_l)
1893 {
1894 if(locNewCDCSuperLayerSeeds_Axial != locNewCDCTrackCircles[loc_l]->dSuperLayerSeeds_Axial)
1895 continue;
1896 //all axial layers are identical: use previous object
1897 locNewCDCTrackCircle = locNewCDCTrackCircles[loc_l];
1898 }
1899 if(locNewCDCTrackCircle == NULL__null)
1900 {
1901 //new combination of axial layers, create new object
1902 if(locNewCDCTrackCircles.size() >= MAX_ALLOWED_TRACK_CIRCLES)
1903 {
1904 if(DEBUG_LEVEL > 10)
1905 cout << "Too many track circles; bailing" << endl;
1906 locCDCTrackCircles.clear();
1907 return false;
1908 }
1909 locNewCDCTrackCircle = Get_Resource_CDCTrackCircle();
1910 locNewCDCTrackCircle->dSuperLayerSeeds_Axial = locNewCDCSuperLayerSeeds_Axial;
1911 if(!locFromInnerStereoFlag) //if on outer stereo, keep inner stereo results (but not outer stereo!!: will save below)
1912 locNewCDCTrackCircle->dSuperLayerSeeds_InnerStereo = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo;
1913 locNewCDCTrackCircles.push_back(locNewCDCTrackCircle); //store new circle for return
1914 locTrackCircleSavedFlag = true;
1915 }
1916 //save this current series of stereo seeds
1917 if(locFromInnerStereoFlag)
1918 locNewCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(locStereoSeedSeries);
1919 else
1920 locNewCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(locStereoSeedSeries);
1921 }
1922 }
1923 if(!locInnerSeedLinkSuccessfulFlag)
1924 {
1925 //this inner seed series was not linked to an axial seed: need to make sure this group is still saved in the "new" deque
1926 //see if should create new DCDCTrackCircle object (axial combo is unique) or use a (probably recently created) existing one (it is not unique)
1927 DCDCTrackCircle* locNewCDCTrackCircle = NULL__null;
1928 for(size_t loc_l = 0; loc_l < locNewCDCTrackCircles.size(); ++loc_l)
1929 {
1930 if(locCDCTrackCircle->dSuperLayerSeeds_Axial != locNewCDCTrackCircles[loc_l]->dSuperLayerSeeds_Axial)
1931 continue;
1932 //all axial layers are identical: use previous object
1933 locNewCDCTrackCircle = locNewCDCTrackCircles[loc_l];
1934 }
1935 if(locNewCDCTrackCircle == NULL__null)
1936 {
1937 //new combination of axial layers, create new object
1938 if(locNewCDCTrackCircles.size() >= MAX_ALLOWED_TRACK_CIRCLES)
1939 {
1940 if(DEBUG_LEVEL > 10)
1941 cout << "Too many track circles; bailing" << endl;
1942 locCDCTrackCircles.clear();
1943 return false;
1944 }
1945 locNewCDCTrackCircle = Get_Resource_CDCTrackCircle();
1946 locNewCDCTrackCircle->dSuperLayerSeeds_Axial = locCDCTrackCircle->dSuperLayerSeeds_Axial;
1947 if(!locFromInnerStereoFlag) //if on outer stereo, keep inner stereo results (but not outer stereo!!: will save below)
1948 locNewCDCTrackCircle->dSuperLayerSeeds_InnerStereo = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo;
1949 locNewCDCTrackCircles.push_back(locNewCDCTrackCircle); //store new circle for return
1950 locTrackCircleSavedFlag = true;
1951 }
1952 //save this current series of stereo seeds
1953 if(locFromInnerStereoFlag)
1954 locNewCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(locStereoSeedSeries);
1955 else
1956 locNewCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(locStereoSeedSeries);
1957 }
1958 }
1959 //if true: no combination of stereo seeds from this track circle was linked as a new object, keep as a unique combination
1960 if(!locTrackCircleSavedFlag)
1961 locNewCDCTrackCircles.push_back(locCDCTrackCircle);
1962 }
1963
1964 locCDCTrackCircles = locNewCDCTrackCircles; //"return" "new" track circle objects
1965 return true;
1966}
1967
1968//-------------------------------------
1969// Link_SuperLayers_FromStereo_ToStereo
1970//-------------------------------------
1971void DTrackCandidate_factory_CDC::Link_SuperLayers_FromStereo_ToStereo(deque<DCDCTrackCircle*>& locCDCTrackCircles, unsigned int locOuterSuperLayer, unsigned int locInnerSuperLayer)
1972{
1973 // Link from a stereo super layer to a stereo super layer.
1974
1975 // loop over track circles
1976 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
1977 {
1978 DCDCTrackCircle* locCDCTrackCircle = locCDCTrackCircles[loc_i];
1979
1980 // if trying to skip a layer, first check to make sure this seed wasn't already linked (to layer "locInnerSuperLayer + 1")
1981 // axial checked here, stereo checked for each stereo series below
1982 if(!locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
1983 {
1984 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.back()->dSuperLayer > locInnerSuperLayer)
1985 continue;
1986 }
1987
1988 // determine if linking from the stereo seeds stored in the dSuperLayerSeeds_InnerStereo or dSuperLayerSeeds_OuterStereo deques
1989 bool locFromInnerStereoFlag = (locInnerSuperLayer < 4);
1990 if(!locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
1991 {
1992 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.back()->dSuperLayer != 4)
1993 locFromInnerStereoFlag = true; //middle axial layer is missing, store stereo layer as inner
1994 }
1995
1996 //get series of seeds to loop over
1997 deque<deque<DCDCSuperLayerSeed*> > locPreLinkedCDCSuperLayerSeeds;
1998 if(locFromInnerStereoFlag)
1999 {
2000 //if on outer stereo seeds but axial seed 4 is missing, use inner stereo seeds
2001 locPreLinkedCDCSuperLayerSeeds = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo;
2002 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.clear(); //reset the existing combos: will re-fill below with the new combos
2003 }
2004 else
2005 {
2006 //use outer stereo seeds
2007 locPreLinkedCDCSuperLayerSeeds = locCDCTrackCircle->dSuperLayerSeeds_OuterStereo; //for looping over
2008 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.clear(); //reset the existing combos: will re-fill below with the new combos
2009 }
2010
2011 //loop over each series of stereo seeds
2012 for(size_t loc_j = 0; loc_j < locPreLinkedCDCSuperLayerSeeds.size(); ++loc_j)
2013 {
2014 //get the last DCDCSuperLayerSeed in this stereo seed series
2015 deque<DCDCSuperLayerSeed*> locStereoSeedSeries = locPreLinkedCDCSuperLayerSeeds[loc_j];
2016 DCDCSuperLayerSeed* locSuperLayerSeed1 = locPreLinkedCDCSuperLayerSeeds[loc_j].back();
2017 if(DEBUG_LEVEL > 10)
2018 cout << "Seed 1 Super Layer, Seed Index = " << locSuperLayerSeed1->dSuperLayer << ", " << locSuperLayerSeed1->dSeedIndex << endl;
2019
2020 bool locInnerSeedLinkSuccessfulFlag = false;
2021 //don't attempt seed link if wrong super layer, or if the inner seed was a definite spiral turn that was turning back inwards, etc.
2022 if((locSuperLayerSeed1->dSuperLayer == locInnerSuperLayer) && Check_IfShouldAttemptLink(locSuperLayerSeed1, true))
2023 {
2024 //attempt to link to the outer superlayer
2025 for(size_t loc_k = 0; loc_k < dSuperLayerSeeds[locOuterSuperLayer - 1].size(); ++loc_k)
2026 {
2027 DCDCSuperLayerSeed* locSuperLayerSeed2 = dSuperLayerSeeds[locOuterSuperLayer - 1][loc_k];
2028 if(DEBUG_LEVEL > 10)
2029 cout << "Seed 2 Super Layer, Seed Index = " << locSuperLayerSeed2->dSuperLayer << ", " << locSuperLayerSeed2->dSeedIndex << endl;
2030 if(!Check_IfShouldAttemptLink(locSuperLayerSeed2, false))
2031 continue; //don't attempt seed link if the outer seed was a definite spiral turn that was turning back outwards, etc.
2032 if(DEBUG_LEVEL > 10)
2033 cout << "Attempting Seed Link" << endl;
2034 if(!Attempt_SeedLink(locSuperLayerSeed1, locSuperLayerSeed2)) //see if seeds are nearby enough to link
2035 continue;
2036 //LINK SUCCESSFUL!!
2037 if(DEBUG_LEVEL > 10)
2038 cout << "LINK SUCCESSFUL" << endl;
2039 locSuperLayerSeed1->linked = true;
2040 locSuperLayerSeed2->linked = true;
2041 locInnerSeedLinkSuccessfulFlag = true;
2042
2043 //create deque of new stereo seed series
2044 deque<DCDCSuperLayerSeed*> locNewStereoSeedSeries = locStereoSeedSeries;
2045 locNewStereoSeedSeries.push_back(locSuperLayerSeed2);
2046
2047 //save new combination of stereo seeds
2048 if(locFromInnerStereoFlag)
2049 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(locNewStereoSeedSeries);
2050 else //outer and middle axial layer isn't missing
2051 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(locNewStereoSeedSeries);
2052 }
2053 }
2054 if(!locInnerSeedLinkSuccessfulFlag)
2055 {
2056 //failed to match, but keep seed series
2057 if(locFromInnerStereoFlag)
2058 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(locStereoSeedSeries);
2059 else //outer and middle axial layer isn't missing
2060 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(locStereoSeedSeries);
2061 }
2062 }
2063 }
2064}
2065
2066//--------------------------
2067// Check_IfShouldAttemptLink
2068//--------------------------
2069bool DTrackCandidate_factory_CDC::Check_IfShouldAttemptLink(const DCDCSuperLayerSeed* locSuperLayerSeed, bool locInnerSeedFlag)
2070{
2071 // don't attempt linking if a definite spiral turn on one of the seeds is turning in the wrong direction
2072 if(locSuperLayerSeed->dSpiralLinkParams.empty())
2073 return true; //should definitely attempt it if not a spiral turn
2074
2075 //get spiral link information
2076 const map<int, DSpiralParams_t>& locSpiralLinkParams = locSuperLayerSeed->dSpiralLinkParams;
2077 bool locSelfLinkFlag = (locSpiralLinkParams.find(locSuperLayerSeed->dSeedIndex) != locSpiralLinkParams.end()); //true if spiral-link is within itself
2078
2079 // determine if turning inwards, outwards, or indeterminate
2080 bool locIsTurningOutwardsFlag = false;
2081 bool locIsTurningInwardsFlag = false;
2082 map<int, DSpiralParams_t>::const_iterator locIterator;
2083 for(locIterator = locSuperLayerSeed->dSpiralLinkParams.begin(); locIterator != locSuperLayerSeed->dSpiralLinkParams.end(); ++locIterator)
2084 {
2085 if(locIterator->second.dDefiniteSpiralTurnRingFlag == -1)
2086 locIsTurningOutwardsFlag = true;
2087 else if(locIterator->second.dDefiniteSpiralTurnRingFlag == 1)
2088 locIsTurningInwardsFlag = true;
2089 }
2090 if(locIsTurningOutwardsFlag == locIsTurningInwardsFlag)
2091 return true; //either not a definite spiral turn (both are false), or indeterminate turning direction (both are true)
2092
2093 //check spiral turn direction
2094 if(locInnerSeedFlag)
2095 {
2096 if(!locSelfLinkFlag)
2097 {
2098 if(locIsTurningInwardsFlag)
2099 {
2100 //spiral turn not linked to itself, inner seed is turning inwards : don't link to next super layer
2101 if(DEBUG_LEVEL > 10)
2102 cout << "Seed1 part of spiral turn in different direction, don't link it here." << endl;
2103 return false;
2104 }
2105 }
2106 else if(locIsTurningOutwardsFlag)
2107 {
2108 //spiral turn linked to itself (single ring), on ring in inner-half of the inner super layer used for matching : don't link to next super layer
2109 if(DEBUG_LEVEL > 10)
2110 cout << "Seed1 part of spiral turn in different direction, don't link it here." << endl;
2111 return false;
2112 }
2113 }
2114 else
2115 {
2116 if(!locSelfLinkFlag)
2117 {
2118 if(locIsTurningOutwardsFlag)
2119 {
2120 //spiral turn not linked to itself, outer seed is turning outwards : don't link to previous super layer
2121 if(DEBUG_LEVEL > 10)
2122 cout << "Seed2 part of spiral turn in different direction, don't link it here." << endl;
2123 return false;
2124 }
2125 }
2126 else if(locIsTurningInwardsFlag)
2127 {
2128 //spiral turn linked to itself (single ring), on ring in outer-half of the outer super layer used for matching : don't link to previous super layer
2129 if(DEBUG_LEVEL > 10)
2130 cout << "Seed2 part of spiral turn in different direction, don't link it here." << endl;
2131 return false;
2132 }
2133 }
2134 return true;
2135}
2136
2137//-----------------
2138// Attempt_SeedLink
2139//-----------------
2140bool DTrackCandidate_factory_CDC::Attempt_SeedLink(DCDCSuperLayerSeed* locSuperLayerSeed1, DCDCSuperLayerSeed* locSuperLayerSeed2)
2141{
2142 //locSuperLayerSeed1 should be the inner of the two
2143 wire_direction_t locWireDirection1 = locSuperLayerSeed1->dWireOrientation;
2144 DCDCRingSeed& locRingSeed1 = locSuperLayerSeed1->dCDCRingSeeds.back(); //largest ring of inner seed selected
2145
2146 //locSuperLayerSeed2 should be the outer of the two
2147 wire_direction_t locWireDirection2 = locSuperLayerSeed2->dWireOrientation;
2148 DCDCRingSeed& locRingSeed2 = locSuperLayerSeed2->dCDCRingSeeds.front(); //smallest ring of outer seed selected
2149
2150 return Attempt_SeedLink(locRingSeed1, locRingSeed2, locWireDirection1, locWireDirection2);
2151}
2152
2153//-----------------
2154// Attempt_SeedLink
2155//-----------------
2156bool DTrackCandidate_factory_CDC::Attempt_SeedLink(DCDCRingSeed& locRingSeed1, DCDCRingSeed& locRingSeed2, wire_direction_t locWireDirection1, wire_direction_t locWireDirection2)
2157{
2158 //attempt seed link between ring-seeds
2159 //should only be called when linking super layers together, and when attempting to link to unused hits
2160 deque<DCDCTrkHit*> &hits1 = locRingSeed1.hits;
2161 if(hits1.empty())
2162 return false;
2163
2164 deque<DCDCTrkHit*> &hits2 = locRingSeed2.hits;
2165 if(hits2.empty())
2166 return false;
2167
2168 const DCDCWire* wire1 = hits1[0]->hit->wire;
2169 const DCDCWire* wire2 = hits2[0]->hit->wire;
2170
2171 // Determine the minimum distance between the two sets of hits
2172 double locMinDist2 = MinDist2(locRingSeed1, locRingSeed2);
2173
2174 // Determine the maximum-allowed transverse distance for linking: is dependent on the orientation of the wires
2175 //if axial, distance is MAX_HIT_DIST
2176 //if stereo, distance is MAX_HIT_DIST + 1/2 of the length of the projection of the straw onto the X-Y plane
2177 //why 1/2? because the wire position (origin) is reported at the midpoint of the straw
2178 double locMaxDist2;
2179 if((locWireDirection1 == WIRE_DIRECTION_AXIAL) && (locWireDirection2 == WIRE_DIRECTION_AXIAL))
2180 locMaxDist2 = MAX_HIT_DIST2;
2181 else if((locWireDirection1 == WIRE_DIRECTION_AXIAL) && (locWireDirection2 != WIRE_DIRECTION_AXIAL))
2182 {
2183 locMaxDist2 = MAX_HIT_DIST + 0.5*wire2->L*fabs(sin(wire2->stereo));
2184 locMaxDist2 *= locMaxDist2;
2185 }
2186 else if((locWireDirection1 != WIRE_DIRECTION_AXIAL) && (locWireDirection2 == WIRE_DIRECTION_AXIAL))
2187 {
2188 locMaxDist2 = MAX_HIT_DIST + 0.5*wire1->L*fabs(sin(wire1->stereo));
2189 locMaxDist2 *= locMaxDist2;
2190 }
2191 else if((locWireDirection1 == WIRE_DIRECTION_STEREORIGHT) && (locWireDirection2 == WIRE_DIRECTION_STEREOLEFT))
2192 {
2193 locMaxDist2 = MAX_HIT_DIST + 0.5*wire1->L*fabs(sin(wire1->stereo)) + 0.5*wire2->L*fabs(sin(wire2->stereo));
2194 locMaxDist2 *= locMaxDist2;
2195 }
2196 else if((locWireDirection1 == WIRE_DIRECTION_STEREOLEFT) && (locWireDirection2 == WIRE_DIRECTION_STEREORIGHT))
2197 {
2198 locMaxDist2 = MAX_HIT_DIST + 0.5*wire1->L*fabs(sin(wire1->stereo)) + 0.5*wire2->L*fabs(sin(wire2->stereo));
2199 locMaxDist2 *= locMaxDist2;
2200 }
2201 else //both stereo left or right
2202 locMaxDist2 = MAX_HIT_DIST2;
2203
2204 double dr = wire2->origin.Perp() - wire1->origin.Perp();
2205 if(DEBUG_LEVEL > 20)
2206 cout << "locMinDist2, locMaxDist2, dr = " << locMinDist2 << ", " << locMaxDist2 << ", " << dr << endl;
2207
2208 //calculate transverse distance, return whether or not it is too large
2209 double locTransverseDist2 = locMinDist2 - dr*dr;
2210 return (locTransverseDist2 < locMaxDist2);
2211}
2212
2213//-------------------
2214// Print_TrackCircles
2215//-------------------
2216void DTrackCandidate_factory_CDC::Print_TrackCircles(deque<DCDCTrackCircle*>& locCDCTrackCircles)
2217{
2218 cout << "Track Circle Super Layer Seeds (Axial, Inner/Outer Stereo):" << endl;
2219 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
2220 {
2221 cout << "Track Circle Index = " << loc_i << endl;
2222 Print_TrackCircle(locCDCTrackCircles[loc_i]);
2223 }
2224}
2225
2226//------------------
2227// Print_TrackCircle
2228//------------------
2229void DTrackCandidate_factory_CDC::Print_TrackCircle(DCDCTrackCircle* locCDCTrackCircle)
2230{
2231 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_j)
2232 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2233 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_j)
2234 {
2235 cout << "Inner Stereo Series " << loc_j << ":" << endl;
2236 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_j].size(); ++loc_k)
2237 cout << "Super Layer, Seed Index = " << locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_j][loc_k]->dSuperLayer << ", " << locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_j][loc_k]->dSeedIndex << endl;
2238 }
2239 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_j)
2240 {
2241 cout << "Outer Stereo Series " << loc_j << ":" << endl;
2242 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j].size(); ++loc_k)
2243 cout << "Super Layer, Seed Index = " << locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j][loc_k]->dSuperLayer << ", " << locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j][loc_k]->dSeedIndex << endl;
2244 }
2245 const DHelicalFit* locFit = locCDCTrackCircle->fit;
2246 if(locFit != NULL__null)
2247 {
2248 cout << "Fit h, x0, y0, r0, phi = " << locFit->h << ", " << locFit->x0 << ", " << locFit->y0 << ", " << locFit->r0 << ", " << locFit->phi << endl;
2249 cout << "Fit Weighted chisq/ndf = " << locCDCTrackCircle->dWeightedChiSqPerDF << endl;
2250 cout << "Stereo Weighted chisq/ndf = " << locCDCTrackCircle->dWeightedChiSqPerDF_Stereo << endl;
2251 }
2252}
2253
2254//--------------------------
2255// Reject_DefiniteSpiralArms
2256//--------------------------
2257void DTrackCandidate_factory_CDC::Reject_DefiniteSpiralArms(deque<DCDCTrackCircle*>& locCDCTrackCircles)
2258{
2259 //disregard all DCDCTrackCircle objects where the innermost super layer is definitely a spiral turn
2260 //e.g. the track has already turned backed inwards towards the target, but then turns back outward again towards the BCAL
2261 deque<DCDCTrackCircle*>::iterator locIterator;
2262 for(locIterator = locCDCTrackCircles.begin(); locIterator != locCDCTrackCircles.end();)
2263 {
2264 DCDCTrackCircle* locCDCTrackCircle = *locIterator;
2265
2266 // get the innermost super layer seed
2267 DCDCSuperLayerSeed* locInnermostSuperLayerSeed = NULL__null;
2268 if(!locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
2269 locInnermostSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_Axial.front();
2270 if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
2271 {
2272 DCDCSuperLayerSeed* locTempSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0].front();
2273 if(locInnermostSuperLayerSeed == NULL__null)
2274 locInnermostSuperLayerSeed = locTempSuperLayerSeed;
2275 else if(locTempSuperLayerSeed->dSuperLayer < locInnermostSuperLayerSeed->dSuperLayer)
2276 locInnermostSuperLayerSeed = locTempSuperLayerSeed;
2277 }
2278 else if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
2279 {
2280 DCDCSuperLayerSeed* locTempSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0].front();
2281 if(locInnermostSuperLayerSeed == NULL__null)
2282 locInnermostSuperLayerSeed = locTempSuperLayerSeed;
2283 else if(locTempSuperLayerSeed->dSuperLayer < locInnermostSuperLayerSeed->dSuperLayer)
2284 locInnermostSuperLayerSeed = locTempSuperLayerSeed;
2285 }
2286 if (locInnermostSuperLayerSeed == NULL__null)
2287 continue; //is impossible, but clears the warning from the static analyzer
2288
2289 //loop over spiral links, see if one of them is a definite spiral link
2290 bool locIsDefinitelyTurningFlag = false;
2291 map<int, DSpiralParams_t>::iterator locSpiralIterator;
2292 for(locSpiralIterator = locInnermostSuperLayerSeed->dSpiralLinkParams.begin(); locSpiralIterator != locInnermostSuperLayerSeed->dSpiralLinkParams.end(); ++locSpiralIterator)
2293 {
2294 if(locSpiralIterator->second.dDefiniteSpiralTurnRingFlag == 0)
2295 continue;
2296 locIsDefinitelyTurningFlag = true;
2297 break;
2298 }
2299
2300 //if definitely a spiral turn in its innermost super layer: then delete the track circle: does not originate from the target
2301 if(locIsDefinitelyTurningFlag)
2302 {
2303 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2304 locIterator = locCDCTrackCircles.erase(locIterator);
2305 }
2306 else
2307 ++locIterator;
2308 }
2309}
2310
2311//----------------------
2312// Drop_IncompleteGroups
2313//----------------------
2314void DTrackCandidate_factory_CDC::Drop_IncompleteGroups(deque<DCDCTrackCircle*>& locCDCTrackCircles)
2315{
2316 // Only interested in groups that contain either:
2317 // At least super layer 1 (forward going particles)
2318 // Or at least one stereo layer and one axial layer
2319 deque<DCDCTrackCircle*>::iterator locIterator;
2320 for(locIterator = locCDCTrackCircles.begin(); locIterator != locCDCTrackCircles.end();)
2321 {
2322 DCDCTrackCircle* locCDCTrackCircle = *locIterator;
2323 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
2324 {
2325 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2326 locIterator = locCDCTrackCircles.erase(locIterator); //no axial super layers
2327 continue;
2328 }
2329
2330 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.front()->dSuperLayer == 1)
2331 {
2332 ++locIterator; //has super layer 1: group is OK
2333 continue;
2334 }
2335
2336 if(locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty() && locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
2337 {
2338 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2339 locIterator = locCDCTrackCircles.erase(locIterator); //no stereo super layers
2340 }
2341 else
2342 ++locIterator; //has at least one axial & one stereo super layer: group is OK
2343 }
2344}
2345
2346//------------
2347// Fit_Circles
2348//------------
2349void DTrackCandidate_factory_CDC::Fit_Circles(deque<DCDCTrackCircle*>& locCDCTrackCircles, bool locFitOnlyIfNullFitFlag, bool locAddStereoLayerIntersectionsFlag, bool locFitDuringLinkingFlag)
2350{
2351 /// Do a quick fit of the 2-D projection of the axial hits in the seed to a circle
2352 /// Include intersection between stereo layer seeds if locAddStereoLayerIntersectionsFlag = true (assumes only one stereo seed series for each inner/outer)
2353 /// Determine the sign of the charge (and correspondingly the initial phi angle)
2354 /// assuming that the majority of hits come from the outgoing part of the track.
2355
2356 /// If the resulting circle passes within MAX_HIT_DIST the majority of the hits,
2357 /// then the fit was a success. Otherwise it is a failure and the DCDCTrackCircle is discarded.
2358
2359 /// locFitOnlyIfNullFitFlag should be false unless just truncated the input set of circles
2360 /// if true, this will skip fitting circles that have DCDCTrackCircle::fit != NULL (i.e. were not truncated)
2361
2362 double locAxialStrawVariance = 0.214401; //[d/sqrt(12)]^2, d = 1.604 = straw diameter
2363 deque<DCDCTrackCircle*>::iterator locIterator;
2364 for(locIterator = locCDCTrackCircles.begin(); locIterator != locCDCTrackCircles.end();)
2365 {
2366 DCDCTrackCircle* locCDCTrackCircle = *locIterator;
2367 size_t locNumAxialSuperLayers = locCDCTrackCircle->dSuperLayerSeeds_Axial.size();
2368
2369 if(locFitDuringLinkingFlag && (locNumAxialSuperLayers < 2))
2370 {
2371 //just trying to reduce number of circles during super layer linking; don't try to fit & don't reject yet
2372 ++locIterator;
2373 continue;
2374 }
2375
2376 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
2377 {
2378 //no axial hits: cannot fit circle: reject
2379 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2380 locIterator = locCDCTrackCircles.erase(locIterator);
2381 continue;
2382 }
2383
2384 if(locFitOnlyIfNullFitFlag && (locCDCTrackCircle->fit != NULL__null))
2385 {
2386 ++locIterator;
2387 continue; //fit is not null: & locFitOnlyIfNullFitFlag is true: circle not truncated, don't refit
2388 }
2389
2390 // Setup the fit (add hits)
2391 DHelicalFit* locFit = Get_Resource_HelicalFit();
2392 unsigned int locNumHitsInFit = 0;
2393 for(size_t loc_i = 0; loc_i < locNumAxialSuperLayers; ++loc_i)
2394 {
2395 deque<DCDCTrkHit*> hits;
2396 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_i]->Get_Hits(hits);
2397 for(size_t k = 0; k < hits.size(); ++k)
2398 {
2399 if(hits[k]->flags & OUT_OF_TIME)
2400 continue;
2401 DVector3 pos = hits[k]->hit->wire->origin;
2402 locFit->AddHitXYZ(pos.x(), pos.y(), pos.z(), locAxialStrawVariance, locAxialStrawVariance, 0.0);
2403 ++locNumHitsInFit;
2404 }
2405 }
2406
2407 //add intersections between stereo super layers if desired
2408 //only uses the first combination of stereo super layers (series)
2409 if(locAddStereoLayerIntersectionsFlag)
2410 {
2411 DCDCSuperLayerSeed* locInnerSuperLayerSeed = locCDCTrackCircle->Get_SuperLayerSeed(2);
2412 DCDCSuperLayerSeed* locOuterSuperLayerSeed = locCDCTrackCircle->Get_SuperLayerSeed(3);
2413 if((locInnerSuperLayerSeed != NULL__null) && (locOuterSuperLayerSeed != NULL__null))
2414 {
2415 // Add intersection between super layers 2 & 3
2416 DVector3 locIntersection = Find_IntersectionBetweenSuperLayers(locInnerSuperLayerSeed, locOuterSuperLayerSeed);
2417 //are these the correct uncertainties?
2418 locFit->AddHitXYZ(locIntersection.x(), locIntersection.y(), locIntersection.z(), locAxialStrawVariance, locAxialStrawVariance, 0.0);
2419 }
2420 locInnerSuperLayerSeed = locCDCTrackCircle->Get_SuperLayerSeed(5);
2421 locOuterSuperLayerSeed = locCDCTrackCircle->Get_SuperLayerSeed(6);
2422 if((locInnerSuperLayerSeed != NULL__null) && (locOuterSuperLayerSeed != NULL__null))
2423 {
2424 // Add intersection between super layers 5 & 6
2425 DVector3 locIntersection = Find_IntersectionBetweenSuperLayers(locInnerSuperLayerSeed, locOuterSuperLayerSeed);
2426 //are these the correct uncertainties?
2427 locFit->AddHitXYZ(locIntersection.x(), locIntersection.y(), locIntersection.z(), locAxialStrawVariance, locAxialStrawVariance, 0.0);
2428 }
2429 }
2430
2431 //place a tighter constraint on the beam center if fewer hits: tracks with detached vertices may not go through the center
2432 double locBeamRMS = BeamRMS0.5*locNumAxialSuperLayers; //1sigma = 0.5, 1.0, 1.5 //3sigma = 1.5, 3.0, 4.5
2433
2434 // Perform the fit
2435 if(locFit->FitCircleRiemann(TARGET_Z, locBeamRMS) != NOERROR)
2436 {
2437 if(DEBUG_LEVEL > 3)
2438 cout << "Riemann fit failed. Attempting regression fit..." << endl;
2439 if(locFit->FitCircle() != NOERROR)
2440 {
2441 if(DEBUG_LEVEL > 3)
2442 cout << "Regression circle fit failed. Trying straight line." << endl;
2443 if(locFit->FitCircleStraightTrack() != NOERROR)
2444 {
2445 if(DEBUG_LEVEL > 3)
2446 cout << "Trying straight line fit failed. Giving up." << endl;
2447 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2448 locIterator = locCDCTrackCircles.erase(locIterator);
2449 continue;
2450 }
2451 }
2452 else
2453 locFit->FindSenseOfRotation();
2454 }
2455 else
2456 locFit->GuessChargeFromCircleFit(); // for Riemann fit
2457
2458 // Check if majority of hits are close to circle. Also calculate the avg drift time for the hits close to the circle.
2459 double x0 = locFit->x0;
2460 double y0 = locFit->y0;
2461 double r0 = locFit->r0;
2462 size_t locNumHitsCloseToCircle = 0;
2463 double locAverageDriftTime = 0.0;
2464 unsigned int locTotalNumHits = 0;
2465 for(size_t loc_i = 0; loc_i < locNumAxialSuperLayers; ++loc_i)
2466 {
2467 deque<DCDCTrkHit*> hits;
2468 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_i]->Get_Hits(hits);
2469 locTotalNumHits += hits.size();
2470 for(size_t k = 0; k < hits.size(); ++k)
2471 {
2472 if(hits[k]->flags & OUT_OF_TIME)
2473 continue;
2474 double dx = hits[k]->hit->wire->origin.X() - x0;
2475 double dy = hits[k]->hit->wire->origin.Y() - y0;
2476 double d = sqrt(dx*dx + dy*dy);
2477 if(DEBUG_LEVEL > 15)
2478 cout << "dist = " << d - r0 << endl;
2479 if(fabs(d - r0) > MAX_HIT_DIST)
2480 continue;
2481 ++locNumHitsCloseToCircle;
2482 locAverageDriftTime += hits[k]->hit->tdrift;
2483 }
2484 }
2485 locAverageDriftTime /= ((double)locNumHitsCloseToCircle);
2486
2487 if(DEBUG_LEVEL > 3)
2488 cout << "Circle fit: Nhits=" << locFit->GetNhits() << " h=" << locFit->h << " N=" << locNumHitsCloseToCircle << " phi=" << locFit->phi << endl;
2489 if(locNumHitsCloseToCircle < MIN_SEED_HITS)
2490 {
2491 if(DEBUG_LEVEL > 3)
2492 cout << "Rejected circle fit due to too few hits on track (N=" << locNumHitsCloseToCircle << " MIN_SEED_HITS=" << MIN_SEED_HITS << ")" << endl;
2493 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2494 locIterator = locCDCTrackCircles.erase(locIterator);
2495 continue;
2496 }
2497
2498 if(locNumHitsCloseToCircle < locTotalNumHits/2)
2499 {
2500 if(DEBUG_LEVEL > 3)
2501 cout << "Rejected circle fit due to minority of hits on track (N=" << locNumHitsCloseToCircle << " locTotalNumHits/2=" << locTotalNumHits/2 << ")" << endl;
2502 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2503 locIterator = locCDCTrackCircles.erase(locIterator);
2504 continue;
2505 }
2506
2507 // Fit is good, save fit results
2508 locCDCTrackCircle->fit = locFit;
2509 double locWeightedChiSqPerDF = ((fabs(locFit->chisq) > 0.0) && (locFit->ndof > 0)) ? locFit->chisq/(float(locFit->ndof*locNumAxialSuperLayers*locNumAxialSuperLayers)) : 9.9E50;
2510 if(DEBUG_LEVEL > 10)
2511 cout << "chisq, ndof, numaxial, weightedchisq = " << locFit->chisq << ", " << locFit->ndof << ", " << locNumAxialSuperLayers << ", " << locWeightedChiSqPerDF << endl;
2512 locCDCTrackCircle->dWeightedChiSqPerDF = locWeightedChiSqPerDF;
2513 locCDCTrackCircle->dAverageDriftTime = locAverageDriftTime;
2514
2515 ++locIterator;
2516 }
2517}
2518
2519//------------------------------------
2520// Find_IntersectionBetweenSuperLayers
2521//------------------------------------
2522DVector3 DTrackCandidate_factory_CDC::Find_IntersectionBetweenSuperLayers(const DCDCSuperLayerSeed* locInnerSuperLayerSeed, const DCDCSuperLayerSeed* locOuterSuperLayerSeed)
2523{
2524 const DCDCRingSeed& locInnerSuperLayerRing = locInnerSuperLayerSeed->dCDCRingSeeds.back(); //last ring of inner super layer
2525 const DCDCRingSeed& locOuterSuperLayerRing = locOuterSuperLayerSeed->dCDCRingSeeds.front(); //first ring of outer super layer
2526
2527 const DCDCWire* first_wire = locInnerSuperLayerRing.hits.front()->hit->wire;
2528 const DCDCWire* second_wire = locOuterSuperLayerRing.hits.front()->hit->wire;
2529
2530 DVector3 u0=first_wire->origin;
2531 DVector3 udir=first_wire->udir;
2532 DVector3 v0=second_wire->origin;
2533 DVector3 vdir=second_wire->udir;
2534 DVector3 diff=u0-v0;
2535 double u_dot_v=udir.Dot(vdir);
2536 double u_dot_diff=udir.Dot(diff);
2537 double v_dot_diff=vdir.Dot(diff);
2538 double scale=1./(1.-u_dot_v*u_dot_v);
2539 double ul=scale*(u_dot_v*v_dot_diff-u_dot_diff);
2540 double vl=scale*(v_dot_diff-u_dot_v*u_dot_diff);
2541 DVector3 pos=0.5*(u0+ul*udir+v0+vl*vdir);
2542
2543 if(DEBUG_LEVEL > 10)
2544 cout << "XYZ intersection between SL" << locInnerSuperLayerSeed->dSuperLayer << " and SL" << locOuterSuperLayerSeed->dSuperLayer << ": " << pos.X() << ", " << pos.Y() << ", " << pos.Z() << endl;
2545 return pos;
2546}
2547
2548/*********************************************************************************************************************************************************************/
2549/*************************************************************** Filter Track Circles and Stereo Wires ***************************************************************/
2550/*********************************************************************************************************************************************************************/
2551
2552//-----------------------
2553// Handle_StereoAndFilter
2554//-----------------------
2555void DTrackCandidate_factory_CDC::Handle_StereoAndFilter(deque<DCDCTrackCircle*>& locCDCTrackCircles, bool locFinalPassFlag)
2556{
2557 // If not on final (refinement) pass: First (potentially) truncate and then filter track circles based on track circle fit results
2558 if(!locFinalPassFlag)
2559 {
2560 Truncate_TrackCircles(locCDCTrackCircles);
2561 Set_HitBitPattern_Axial(locCDCTrackCircles);
2562 Filter_TrackCircles_Axial(locCDCTrackCircles);
2563 if(DEBUG_LEVEL > 5)
2564 {
2565 cout << "post filter clone seeds" << endl;
2566 Print_TrackCircles(locCDCTrackCircles);
2567 }
2568 }
2569
2570 // Create new stereo super layer seeds and select the best ones.
2571 //This is done one track at a time to prevent memory spikes (memory is recycled as "new" stereo hits are rejected)
2572 deque<DCDCTrackCircle*>::iterator locIterator;
2573 size_t locCircleCounter = 0;
2574 for(locIterator = locCDCTrackCircles.begin(); locIterator != locCDCTrackCircles.end();)
2575 {
2576 if(DEBUG_LEVEL > 5)
2577 cout << "Create new Super Layer Seeds for Track Circle " << locCircleCounter << endl;
2578 // Create new super layer seeds: find the intersection between the stereo hits and the circle fit and create new seeds with that information
2579 Create_NewCDCSuperLayerSeeds(*locIterator);
2580 if(DEBUG_LEVEL > 5)
2581 cout << "Select Super Layer Seeds for Track Circle " << locCircleCounter << endl;
2582 // Select the combination of super layer seeds that give the best determination of theta/z for this track.
2583 // Rejects the track if on the final pass and no valid theta/z can be calculated.
2584 if(Select_CDCSuperLayerSeeds(*locIterator, locFinalPassFlag))
2585 ++locIterator;
2586 else
2587 {
2588 Recycle_DCDCTrackCircle(*locIterator); //recycle
2589 locIterator = locCDCTrackCircles.erase(locIterator);
2590 }
2591 ++locCircleCounter;
2592 }
2593 Set_HitBitPattern_All(locCDCTrackCircles);
2594
2595 // If not on final (refinement) pass: Filter track circles based on stereo results
2596 if(!locFinalPassFlag)
2597 {
2598 if(DEBUG_LEVEL > 5)
2599 {
2600 cout << "stereo-selected track circles" << endl;
2601 Print_TrackCircles(locCDCTrackCircles);
2602 }
2603 // Filter out duplicates seeds and definite spiral arms.
2604 Filter_TrackCircles_Stereo(locCDCTrackCircles);
2605 if(DEBUG_LEVEL > 5)
2606 {
2607 cout << "stereo-filtered track circles" << endl;
2608 Print_TrackCircles(locCDCTrackCircles);
2609 }
2610 }
2611}
2612
2613//------------------------
2614// Set_HitBitPattern_Axial
2615//------------------------
2616void DTrackCandidate_factory_CDC::Set_HitBitPattern_Axial(deque<DCDCTrackCircle*>& locCDCTrackCircles)
2617{
2618 unsigned int locNumBits = 8*sizeof(unsigned int);
2619 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
2620 {
2621 DCDCTrackCircle* locCDCTrackCircle = locCDCTrackCircles[loc_i];
2622 locCDCTrackCircle->HitBitPattern.clear();
2623 locCDCTrackCircle->HitBitPattern.resize(dNumCDCHits/(8*sizeof(unsigned int)) + 1);
2624 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_j)
2625 {
2626 deque<DCDCTrkHit*> locHits;
2627 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_j]->Get_Hits(locHits);
2628 for(size_t loc_k = 0; loc_k < locHits.size(); ++loc_k)
2629 locCDCTrackCircle->HitBitPattern[locHits[loc_k]->index/locNumBits] |= 1 << locHits[loc_k]->index % locNumBits;
2630 }
2631 }
2632}
2633
2634//----------------------
2635// Truncate_TrackCircles
2636//----------------------
2637void DTrackCandidate_factory_CDC::Truncate_TrackCircles(deque<DCDCTrackCircle*>& locCDCTrackCircles)
2638{
2639 if(locCDCTrackCircles.empty())
2640 return;
2641
2642 // This routine is designed to save tracks that exit the drift chamber early (e.g. before SL7) when there are other tracks nearby (in phi)
2643 // The problem is when these tracks get mixed together, the track that goes most-radially-outward in the CDC generally wins
2644 // e.g. A track not reaching SL7 can match to the other track's SL7, so its fit is worse than it should be
2645 // And, if the two tracks share many hits (such as SL7), then the track not hitting SL7 tends to get rejected
2646
2647 // It should almost be impossible for two tracks to have identical DCDCSuperLayerSeed's AND for all hits to belong to both tracks.
2648 // Two crossing tracks should almost always have different DCDCSuperLayerSeed's that share hits between them.
2649 // If the DCDCSuperLayerSeed truly ought to belong to both tracks, stripping hits won't kill the track anyway: it should still be reconstructable
2650
2651 // To save these tracks, look for pairs of tracks that have identical axial DCDCSuperLayerSeed's: first in super layer 7
2652 // If the seeds in SL7 are identical, strip SL6 & SL7 from the track with the worse circle-fit weighted chisq/ndf.
2653 // If the seeds in SL4 are also identical in this pair, strip everything but SL1 & SL2 from the track with the worse circle-fit weighted chisq/ndf and refit it.
2654 // If the axial super layer seeds in the truncated circle are not unique, merge it with the other existing DCDCTrackCircle
2655 // If this truncated DCDCTrackCircle is merely a subset of a different DCDCTrackCircle, delete it.
2656 // Refit the newly-truncated track circles.
2657
2658 // Next look for pairs of tracks that have identical DCDCSuperLayerSeed's in super layer 4
2659 // If the track with the worse circle-fit weighted chisq/ndf has an SL7, DO NOT truncate it (it is a unique SL7 (else would have been rejected earlier))
2660 // Otherwise, if the seeds in SL4 are identical, strip SL3+ from the track with the worse circle-fit weighted chisq/ndf and refit it.
2661 // If the axial super layer seeds in the truncated circle are not unique, merge it with the other existing DCDCTrackCircle
2662 // If this truncated DCDCTrackCircle is merely a subset of a different DCDCTrackCircle, delete it.
2663 // Refit the newly-truncated track circles.
2664
2665 //first initialize "DCDCTrackCircle::dHasNonTruncatedSeedsFlag" variables
2666 //these are useful for determining whether or not any of the stereo seeds in the track circle are unique, or whether they all came from a truncation
2667 //this is necessary because after truncating a circle, it may have the same axial super layers as another track circle, with which it will be merged.
2668 //You need to know if any of the stereo combinations in a track circle are unique when determining whether the truncation result is merely a subset of another track
2669 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
2670 {
2671 if(!locCDCTrackCircles[loc_i]->dSuperLayerSeeds_InnerStereo.empty())
2672 locCDCTrackCircles[loc_i]->dHasNonTruncatedSeedsFlag_InnerStereo = true;
2673 if(!locCDCTrackCircles[loc_i]->dSuperLayerSeeds_OuterStereo.empty())
2674 locCDCTrackCircles[loc_i]->dHasNonTruncatedSeedsFlag_OuterStereo = true;
2675 else if(locCDCTrackCircles[loc_i]->Get_LastSuperLayerSeed()->dSuperLayer > 4)
2676 locCDCTrackCircles[loc_i]->dHasNonTruncatedSeedsFlag_OuterStereo = true; //e.g. SL4 is missing, so outers are grouped with inners
2677 }
2678
2679 //assumes input circles are sorted, with largest chisq/ndf first and smallest last
2680 //want to compare the worst fit to the best fit
2681 deque<DCDCTrackCircle*>::iterator locIterator_Validating, locIterator_ToCompareTo;
2682
2683 // FIRST CHECK FOR SAME SUPER LAYER SEED IN SL7
2684 bool locTruncationPerformedFlag = false;
2685 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end(); ++locIterator_Validating)
2686 {
2687 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating; //this has the worst circle-fit weighted chisq/ndf (and decreasing)
2688 if(DEBUG_LEVEL > 10)
2689 {
2690 cout << "validating: search for SL7 truncation for circle with axial seeds:" << endl;
2691 for(size_t loc_j = 0; loc_j < locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.size(); ++loc_j)
2692 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2693 }
2694
2695 DCDCSuperLayerSeed* locSuperLayerSeed_Validating = locCDCTrackCircle_Validating->Get_SuperLayerSeed(7);
2696 if(locSuperLayerSeed_Validating == NULL__null)
2697 continue; //this track circle has no SL7
2698
2699 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
2700 {
2701 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo; //this has the best circle-fit weighted chisq/ndf (and increasing)
2702 if(DEBUG_LEVEL > 10)
2703 {
2704 cout << "to-compare-to: search for SL7 truncation for circle with axial seeds:" << endl;
2705 for(size_t loc_j = 0; loc_j < locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial.size(); ++loc_j)
2706 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2707 }
2708
2709 DCDCSuperLayerSeed* locSuperLayerSeed_ToCompareTo = locCDCTrackCircle_ToCompareTo->Get_SuperLayerSeed(7);
2710 if(locSuperLayerSeed_Validating != locSuperLayerSeed_ToCompareTo)
2711 continue; //different seed for SL7
2712
2713 //track circles have identical seeds in SL7: should almost never be possible for both to be good tracks AND for all of the hits to belong to both
2714 // if two tracks are crossing they should almost always have different super layer seeds (that share hits)
2715 // if they are somehow both good tracks, stripping hits won't be the end of the world: track should still be reconstructable with a subset of them
2716
2717 //check to see if SL4 is identical also
2718 locSuperLayerSeed_Validating = locCDCTrackCircle_Validating->Get_SuperLayerSeed(4);
2719 locSuperLayerSeed_ToCompareTo = locCDCTrackCircle_ToCompareTo->Get_SuperLayerSeed(4);
2720 if(locSuperLayerSeed_Validating == locSuperLayerSeed_ToCompareTo)
2721 {
2722 // SL4 is identical (or missing from both): strip everything from (and including) SL3 and outwards from the track with lower chisq/ndf
2723 //don't trust SL3 since it led to SL4: hit selector can (in theory) pick up the hits later if needed
2724 //impossible for SL1 to also be identical: would be same object because all axials would be the same
2725 if(DEBUG_LEVEL > 5)
2726 cout << "SL7's and SL4's identical: truncate to SL2" << endl;
2727 locCDCTrackCircle_Validating->Truncate_Circle(2); //2: new last super layer
2728 if(DEBUG_LEVEL > 20)
2729 {
2730 cout << "post truncate" << endl;
2731 Print_TrackCircle(locCDCTrackCircle_Validating);
2732 }
2733 }
2734 else
2735 {
2736 // SL4 is different: strip SL6 & SL7 from the track with lower chisq/ndf
2737 //don't trust SL6 since it led to SL7: hit selector can (in theory) pick up the hits later if needed
2738 if(DEBUG_LEVEL > 5)
2739 cout << "SL7's identical (but not SL4's): truncate to SL5" << endl;
2740 locCDCTrackCircle_Validating->Truncate_Circle(5); //5: new last super layer
2741 if(DEBUG_LEVEL > 20)
2742 {
2743 cout << "post truncate" << endl;
2744 Print_TrackCircle(locCDCTrackCircle_Validating);
2745 }
2746 }
2747
2748 //reset fit
2749 dHelicalFitPool_Available.push_back(locCDCTrackCircle_Validating->fit); //will redo the fit: recycle the memory
2750 locCDCTrackCircle_Validating->fit = NULL__null; //indicate need to reperform fit
2751
2752 //update truncation sources
2753 locCDCTrackCircle_Validating->dTruncationSourceCircles.push_back(locCDCTrackCircle_ToCompareTo);
2754
2755 locTruncationPerformedFlag = true;
2756 break; //truncation successful
2757 }
2758 }
2759
2760 if(locTruncationPerformedFlag)
2761 {
2762 //now merge any track circles that have identical axial super layers
2763 //e.g. two tracks have SL1 & SL4 but different SL7, and their SL7's are rejected by other tracks who have the same SL7s
2764 //loop order doesn't really matter here, keeping consistent anyway
2765 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2766 {
2767 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2768 bool locMergedTrackCircleFlag = false;
2769 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
2770 {
2771 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2772 if(locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial != locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial)
2773 continue; //not identical
2774 //identical axial super layers: merge track circles (absorb the "Validating" one into the "ToCompareTo" one //which is which doesn't matter)
2775 if(DEBUG_LEVEL > 20)
2776 {
2777 cout << "sl7 merging circles: validating = " << endl;
2778 Print_TrackCircle(locCDCTrackCircle_Validating);
2779 cout << "sl7 merging circles: to-compare-to = " << endl;
2780 Print_TrackCircle(locCDCTrackCircle_ToCompareTo);
2781 }
2782 locCDCTrackCircle_ToCompareTo->Absorb_TrackCircle(locCDCTrackCircle_Validating);
2783 if(DEBUG_LEVEL > 20)
2784 {
2785 cout << "sl7 merge circles: output = " << endl;
2786 Print_TrackCircle(locCDCTrackCircle_ToCompareTo);
2787 }
2788 locMergedTrackCircleFlag = true;
2789 break;
2790 }
2791 if(locMergedTrackCircleFlag)
2792 {
2793 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
2794 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
2795 }
2796 else
2797 ++locIterator_Validating;
2798 }
2799
2800 //now check to see if any of the newly-truncated track circles is merely a subset of a different circle (regardless of which chisq/ndf is lower)
2801 //is a subset if the axials are a subset AND the outermost stereo layers dHasNonTruncatedSeedsFlag is false
2802 //if one is a subset of another, delete it
2803 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2804 {
2805 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2806 if(locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.size() == 3)
2807 {
2808 ++locIterator_Validating;
2809 continue; //not going to be a subset
2810 }
2811 if(DEBUG_LEVEL > 20)
2812 {
2813 cout << "sl7 checking-for-subsets: validating = " << endl;
2814 Print_TrackCircle(locCDCTrackCircle_Validating);
2815 }
2816 bool locRejectTrackFlag = false;
2817 for(locIterator_ToCompareTo = locCDCTrackCircles.begin(); locIterator_ToCompareTo != locCDCTrackCircles.end(); ++locIterator_ToCompareTo)
2818 {
2819 if(locIterator_ToCompareTo == locIterator_Validating)
2820 continue;
2821 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2822 if(DEBUG_LEVEL > 20)
2823 {
2824 cout << "sl7 checking-for-subsets: to-compare-to = " << endl;
2825 Print_TrackCircle(locCDCTrackCircle_ToCompareTo);
2826 }
2827
2828 if(!locCDCTrackCircle_ToCompareTo->Check_IfInputIsSubset(locCDCTrackCircle_Validating))
2829 continue; //not a subset
2830
2831 if(DEBUG_LEVEL > 10)
2832 cout << "rejecting subset circle" << endl;
2833 locRejectTrackFlag = true; //is a subset
2834 break;
2835 }
2836 if(locRejectTrackFlag)
2837 {
2838 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
2839 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
2840 }
2841 else
2842 ++locIterator_Validating;
2843 }
2844
2845 //now fit the newly-truncated track circles
2846 Fit_Circles(locCDCTrackCircles, true, false); //true: fit only truncated circles //false: don't add stereo intersections
2847 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByChiSqPerNDFDecreasing); //sort by fit chisq/ndf
2848 if(DEBUG_LEVEL > 5)
2849 {
2850 cout << "Post-SL7-turncation track circles" << endl;
2851 Print_TrackCircles(locCDCTrackCircles);
2852 }
2853 }
2854
2855 // NOW CHECK FOR SAME SUPER LAYER SEED IN SL4
2856 locTruncationPerformedFlag = false;
2857 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2858 {
2859 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2860 if(DEBUG_LEVEL > 10)
2861 {
2862 cout << "validating: search for SL4 truncation for circle with axial seeds:" << endl;
2863 for(size_t loc_j = 0; loc_j < locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.size(); ++loc_j)
2864 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2865 }
2866
2867 DCDCSuperLayerSeed* locSuperLayerSeed_Validating = locCDCTrackCircle_Validating->Get_SuperLayerSeed(4);
2868 if(locSuperLayerSeed_Validating == NULL__null)
2869 {
2870 ++locIterator_Validating;
2871 continue; //this track circle has no SL4
2872 }
2873
2874 if(locCDCTrackCircle_Validating->Get_SuperLayerSeed(7) != NULL__null)
2875 {
2876 //this track circle has a unique SL7 (if not unique would have been truncated earlier): do not truncate it
2877 //rejecting SL4 from the track with the SL7 would leave an unphysical combination
2878 //this track may have a low chisq/ndf because there is a kink in the track, or maybe the eloss is large and the circle doesn't quite catch SL7 very well
2879 //if the SL7 is truly bad (e.g. slightly different from a different, true SL7), then the 50% common-hit requirement should kill it (if SL4 is indeed identical)
2880 ++locIterator_Validating;
2881 continue;
2882 }
2883
2884 DCDCSuperLayerSeed* locSuperLayerSeed1_Validating = locCDCTrackCircle_Validating->Get_SuperLayerSeed(1);
2885 bool locRejectTrackFlag = false;
2886 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
2887 {
2888 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2889 if(DEBUG_LEVEL > 10)
2890 {
2891 cout << "to-compare-to: search for SL4 truncation for circle with axial seeds:" << endl;
2892 for(size_t loc_j = 0; loc_j < locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial.size(); ++loc_j)
2893 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2894 }
2895
2896 DCDCSuperLayerSeed* locSuperLayerSeed_ToCompareTo = locCDCTrackCircle_ToCompareTo->Get_SuperLayerSeed(4);
2897 if(locSuperLayerSeed_Validating != locSuperLayerSeed_ToCompareTo)
2898 continue; //different seed for SL4
2899
2900 //SL4 is identical, check status of SL1
2901 DCDCSuperLayerSeed* locSuperLayerSeed1_ToCompareTo = locCDCTrackCircle_ToCompareTo->Get_SuperLayerSeed(1);
2902 if(locSuperLayerSeed1_Validating == locSuperLayerSeed1_ToCompareTo)
2903 {
2904 //SL1 & SL4 are identical: only difference is that locCDCTrackCircle_ToCompareTo has SL7
2905 //locCDCTrackCircle_Validating is merely a subset of locCDCTrackCircle_ToCompareTo (which has a better chisq/ndf): reject it
2906 if(DEBUG_LEVEL > 5)
2907 cout << "SL1 and SL4 are identical, while SL7 of validating is missing: reject validating track" << endl;
2908 locRejectTrackFlag = true;
2909 break;
2910 }
2911
2912 //track circles have identical seeds in SL4, and at least one track does not have an SL7 (although both may not):
2913 //should almost never be possible for both to be good tracks AND for all of the hits to belong to both
2914 // if two tracks are crossing they should almost always have different super layer seeds (that share hits)
2915 // if they are somehow both good tracks, stripping hits won't be the end of the world: track should still be reconstructable with a subset of them
2916
2917 //truncate the circle //don't trust SL3 since it led to SL4: hit selector can (in theory) pick up the hits later if needed
2918 if(DEBUG_LEVEL > 5)
2919 cout << "SL4 is identical, SL1 is not, while SL7 of validating is missing: truncate to SL2" << endl;
2920 locCDCTrackCircle_Validating->Truncate_Circle(2); //2: new last super layer
2921
2922 //reset fit if not already done
2923 if(locCDCTrackCircle_Validating->fit != NULL__null)
2924 {
2925 dHelicalFitPool_Available.push_back(locCDCTrackCircle_Validating->fit); //will redo the fit: recycle the memory
2926 locCDCTrackCircle_Validating->fit = NULL__null; //indicate need to reperform fit
2927 }
2928
2929 //update truncation sources
2930 bool locIsAlreadyTruncationSourceFlag = false;
2931 for(size_t loc_i = 0; loc_i < locCDCTrackCircle_Validating->dTruncationSourceCircles.size(); ++loc_i)
2932 {
2933 if(locCDCTrackCircle_Validating->dTruncationSourceCircles[loc_i] != locCDCTrackCircle_ToCompareTo)
2934 continue;
2935 locIsAlreadyTruncationSourceFlag = true;
2936 break;
2937 }
2938 if(!locIsAlreadyTruncationSourceFlag)
2939 locCDCTrackCircle_Validating->dTruncationSourceCircles.push_back(locCDCTrackCircle_ToCompareTo);
2940
2941 locTruncationPerformedFlag = true;
2942 break; //truncation successful
2943 }
2944
2945 if(locRejectTrackFlag)
2946 {
2947 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
2948 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
2949 }
2950 else
2951 ++locIterator_Validating;
2952 }
2953
2954 if(locTruncationPerformedFlag)
2955 {
2956 //now merge any track circles that have identical axial super layers
2957 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2958 {
2959 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2960 bool locMergedTrackCircleFlag = false;
2961 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
2962 {
2963 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2964 if(locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial != locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial)
2965 continue; //not identical
2966 //identical axial super layers: merge track circles (absorb the "Validating" one into the "ToCompareTo" one //which is which doesn't matter)
2967 locCDCTrackCircle_ToCompareTo->Absorb_TrackCircle(locCDCTrackCircle_Validating);
2968 locMergedTrackCircleFlag = true;
2969 break;
2970 }
2971 if(locMergedTrackCircleFlag)
2972 {
2973 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
2974 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
2975 }
2976 else
2977 ++locIterator_Validating;
2978 }
2979
2980 //now check to see if any of the newly-truncated track circles is merely a subset of a different circle (regardless of which chisq/ndf is lower)
2981 //is a subset if the axials are a subset AND the outermost stereo layers dHasNonTruncatedSeedsFlag is false
2982 //if one is a subset of another, delete it
2983 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2984 {
2985 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2986 bool locRejectTrackFlag = false;
2987 if(DEBUG_LEVEL > 20)
2988 {
2989 cout << "sl4 checking-for-subsets: validating = " << endl;
2990 Print_TrackCircle(locCDCTrackCircle_Validating);
2991 }
2992 for(locIterator_ToCompareTo = locCDCTrackCircles.begin(); locIterator_ToCompareTo != locCDCTrackCircles.end(); ++locIterator_ToCompareTo)
2993 {
2994 if(locIterator_ToCompareTo == locIterator_Validating)
2995 continue;
2996 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2997 if(DEBUG_LEVEL > 20)
2998 {
2999 cout << "sl4 checking-for-subsets: to-compare-to = " << endl;
3000 Print_TrackCircle(locCDCTrackCircle_ToCompareTo);
3001 }
3002
3003 if(!locCDCTrackCircle_ToCompareTo->Check_IfInputIsSubset(locCDCTrackCircle_Validating))
3004 continue; //not a subset
3005
3006 locRejectTrackFlag = true; //is a subset
3007 if(DEBUG_LEVEL > 10)
3008 cout << "rejecting subset circle" << endl;
3009 break;
3010 }
3011 if(locRejectTrackFlag)
3012 {
3013 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
3014 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
3015 }
3016 else
3017 ++locIterator_Validating;
3018 }
3019
3020 //now fit the newly-truncated track circles
3021 Fit_Circles(locCDCTrackCircles, true, false); //true: fit only truncated circles //false: don't add stereo intersections
3022 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByChiSqPerNDFDecreasing); //sort by fit chisq/ndf
3023 if(DEBUG_LEVEL > 5)
3024 {
3025 cout << "Post-SL4-turncation track circles" << endl;
3026 Print_TrackCircles(locCDCTrackCircles);
3027 }
3028 }
3029}
3030
3031//--------------------------
3032// Filter_TrackCircles_Axial
3033//--------------------------
3034void DTrackCandidate_factory_CDC::Filter_TrackCircles_Axial(deque<DCDCTrackCircle*>& locCDCTrackCircles)
3035{
3036 if(locCDCTrackCircles.empty())
3037 return;
3038
3039 //assumes input circles are sorted, with largest chisq/ndf first and smallest last
3040 //want to compare the worst fit to the best fit
3041 deque<DCDCTrackCircle*>::iterator locIterator_Validating, locIterator_ToCompareTo;
3042
3043 //FIRST: If circles share > MAX_COMMON_HIT_FRACTION of axial hits, reject circle with larger chisq/ndf
3044 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
3045 {
3046 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
3047 if(locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.empty())
3048 continue; //no axial hits to share (somehow)
3049
3050 size_t locNumHits_Validating = 0;
3051 deque<DCDCTrkHit*> hits;
3052 for(size_t loc_i = 0; loc_i < locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.size(); ++loc_i)
3053 {
3054 locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_i]->Get_Hits(hits);
3055 locNumHits_Validating += hits.size();
3056 }
3057
3058 bool locRejectTrackCircleFlag = false;
3059 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
3060 {
3061 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
3062 if(locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial.empty())
3063 continue; //no axial hits to share (somehow)
3064
3065 //If seeds share > MAX_COMMON_HIT_FRACTION of hits, reject seed with larger chisq/ndf
3066 size_t locNumCommonHits = 0;
3067 size_t locNumWords = locCDCTrackCircle_Validating->HitBitPattern.size();
3068 for(size_t loc_i = 0; loc_i < locNumWords; ++loc_i)
3069 locNumCommonHits += bitcount(locCDCTrackCircle_Validating->HitBitPattern[loc_i] & locCDCTrackCircle_ToCompareTo->HitBitPattern[loc_i]);
3070 double locHitFraction = double(locNumCommonHits)/double(locNumHits_Validating);
3071
3072 if(locHitFraction > MAX_COMMON_HIT_FRACTION)
3073 {
3074 locRejectTrackCircleFlag = true;
3075 break;
3076 }
3077 }
3078 if(locRejectTrackCircleFlag)
3079 {
3080 //free up some memory by clearing the seed deques via reset
3081 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
3082 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
3083 }
3084 else
3085 ++locIterator_Validating; //track circle is valid (for now)
3086 }
3087}
3088
3089//-----------------------------
3090// Create_NewCDCSuperLayerSeeds
3091//-----------------------------
3092void DTrackCandidate_factory_CDC::Create_NewCDCSuperLayerSeeds(DCDCTrackCircle* locCDCTrackCircle)
3093{
3094 // Create new stereo DCDCSuperLayerSeed objects, finding the intersections of each stereo wire with the fit circle
3095
3096 map<DCDCSuperLayerSeed*, DCDCSuperLayerSeed*> locConvertedSuperLayerSeeds;
3097 map<DCDCSuperLayerSeed*, DCDCSuperLayerSeed*>::iterator locMapIterator; //map from orig super layer to new super layer
3098 map<DCDCTrkHit*, DCDCTrkHit*> locProjectedStereoHitMap; //map from orig (super layer, non-circle-projected) stereo hit to circle-projected (hit-z-group) hit
3099
3100 //inner stereo
3101 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
3102 {
3103 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i].size(); ++loc_j)
3104 {
3105 DCDCSuperLayerSeed* locCDCSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_j];
3106 locMapIterator = locConvertedSuperLayerSeeds.find(locCDCSuperLayerSeed);
3107 if(locMapIterator != locConvertedSuperLayerSeeds.end())
3108 {
3109 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_j] = locMapIterator->second;
3110 continue; //already converted
3111 }
3112 DCDCSuperLayerSeed* locNewCDCSuperLayerSeed = Create_NewStereoSuperLayerSeed(locCDCSuperLayerSeed, locCDCTrackCircle, locProjectedStereoHitMap);
3113 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_j] = locNewCDCSuperLayerSeed;
3114 locConvertedSuperLayerSeeds[locCDCSuperLayerSeed] = locNewCDCSuperLayerSeed;
3115 }
3116 }
3117
3118 //outer stereo
3119 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_i)
3120 {
3121 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i].size(); ++loc_j)
3122 {
3123 DCDCSuperLayerSeed* locCDCSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i][loc_j];
3124 locMapIterator = locConvertedSuperLayerSeeds.find(locCDCSuperLayerSeed);
3125 if(locMapIterator != locConvertedSuperLayerSeeds.end())
3126 {
3127 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i][loc_j] = locMapIterator->second;
3128 continue; //already converted
3129 }
3130 DCDCSuperLayerSeed* locNewCDCSuperLayerSeed = Create_NewStereoSuperLayerSeed(locCDCSuperLayerSeed, locCDCTrackCircle, locProjectedStereoHitMap);
3131 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i][loc_j] = locNewCDCSuperLayerSeed;
3132 locConvertedSuperLayerSeeds[locCDCSuperLayerSeed] = locNewCDCSuperLayerSeed;
3133 }
3134 }
3135}
3136
3137//-------------------------------
3138// Create_NewStereoSuperLayerSeed
3139//-------------------------------
3140DTrackCandidate_factory_CDC::DCDCSuperLayerSeed* DTrackCandidate_factory_CDC::Create_NewStereoSuperLayerSeed(DCDCSuperLayerSeed* locCDCSuperLayerSeed, const DCDCTrackCircle* locCDCTrackCircle, map<DCDCTrkHit*, DCDCTrkHit*>& locProjectedStereoHitMap)
3141{
3142 //locProjectedStereoHitMap is map from orig (super layer, non-circle-projected) stereo hit to circle-projected hit
3143 DCDCSuperLayerSeed* locNewCDCSuperLayerSeed = Get_Resource_CDCSuperLayerSeed();
3144 *locNewCDCSuperLayerSeed = *locCDCSuperLayerSeed;
3145
3146 // Project all stereo hits in this super layer onto the circle fit
3147
3148 for(size_t loc_i = 0; loc_i < locCDCSuperLayerSeed->dCDCRingSeeds.size(); ++loc_i)
3149 {
3150 deque<DCDCTrkHit*>& hits = locCDCSuperLayerSeed->dCDCRingSeeds[loc_i].hits;
3151 deque<DCDCTrkHit*> locProjectedHits;
3152 for(size_t loc_l = 0; loc_l < hits.size(); ++loc_l)
3153 {
3154 if(fabs(hits[loc_l]->hit->tdrift - locCDCTrackCircle->dAverageDriftTime) > MAX_SEED_TIME_DIFF)
3155 continue; // Ignore hits that are out of time with the group
3156
3157 // If haven't done so already, Calculate intersection points between circle and stereo wire
3158 DCDCTrkHit* locProjectedCDCTrkHit = NULL__null;
3159 map<DCDCTrkHit*, DCDCTrkHit*>::iterator locHitIterator = locProjectedStereoHitMap.find(hits[loc_l]);
3160 if(locHitIterator == locProjectedStereoHitMap.end())
3161 {
3162 // Clone the hit and set it's stereo-hit-position
3163 DVector3 locStereoHitPos;
3164 double locPhiStereo = 0.0, var_z = 9.9E9;
3165 locProjectedCDCTrkHit = Get_Resource_CDCTrkHit();
3166 *locProjectedCDCTrkHit = *hits[loc_l];
3167 //if below is false: wire doesn't intersect the circle: in this case, don't reject hit outright: ignore for theta/z, but let wire-based tracking try to use it
3168 //e.g., track has a spiral turn in SL6, and since there is no SL7, the circle-fit is extrapolated into SL6 and doesn't quite catch the spiral turn
3169 if(Calc_StereoPosition(locProjectedCDCTrkHit->hit->wire, locCDCTrackCircle->fit, locStereoHitPos, var_z, locPhiStereo))
3170 locProjectedCDCTrkHit->dValidStereoHitPosFlag = true;
3171 locProjectedCDCTrkHit->dStereoHitPos = locStereoHitPos;
3172 locProjectedCDCTrkHit->var_z = var_z;
3173 locProjectedCDCTrkHit->dPhiStereo = locPhiStereo;
3174 dStereoHitNumUsedMap[locProjectedCDCTrkHit] = 1;
3175 }
3176 else
3177 {
3178 //hit was already projected onto this circle (e.g. in a different super layer seed), just reuse the results/memory
3179 locProjectedCDCTrkHit = locHitIterator->second;
3180 ++dStereoHitNumUsedMap[locProjectedCDCTrkHit];
3181 }
3182
3183 // Save the hit
3184 locProjectedHits.push_back(locProjectedCDCTrkHit);
3185 }
3186 locNewCDCSuperLayerSeed->dCDCRingSeeds[loc_i].hits = locProjectedHits;
3187 }
3188
3189 return locNewCDCSuperLayerSeed;
3190}
3191
3192//--------------------
3193// Calc_StereoPosition
3194//--------------------
3195bool DTrackCandidate_factory_CDC::Calc_StereoPosition(const DCDCWire *wire, const DHelicalFit* fit, DVector3 &pos, double &var_z, double& locPhiStereo, double d)
3196{
3197 // Calculate intersection point between circle and stereo wire
3198 DVector3 origin = wire->origin;
3199 DVector3 dir = (1./wire->udir.z())*wire->udir;
3200 double dx = origin.x() - fit->x0;
3201 double dy = origin.y() - fit->y0;
3202 double ux = dir.x();
3203 double uy = dir.y();
3204 double temp1 = ux*ux + uy*uy;
3205 double temp2 = ux*dy - uy*dx;
3206 double b = -ux*dx - uy*dy;
3207 double dr = fit->r0 - d;
3208 double r0_sq = dr*dr;
3209 double A = r0_sq*temp1 - temp2*temp2;
3210
3211 // Check that this wire intersects this circle
3212 if(A < 0.0)
3213 return false; // line along wire does not intersect circle, ever.
3214
3215 // Guess for variance for z: assume straw cell size??
3216 double temp = 1.6/sin(wire->stereo);
3217 var_z = temp*temp/12.;
3218
3219 // Calculate intersection points for the two roots
3220 double B = sqrt(A);
3221 double dz1 = (b - B)/temp1;
3222 double dz2 = (b + B)/temp1;
3223
3224 if(DEBUG_LEVEL > 15)
3225 cout<<"dz1="<<dz1<<" dz2="<<dz2<<endl;
3226
3227 // At this point we must decide which value of alpha to use.
3228 // For now, we just use the value closest to zero (i.e. closest to
3229 // the center of the wire).
3230 double dz = dz1;
3231 if(fabs(dz2) < fabs(dz1))
3232 dz = dz2;
3233
3234 // Compute the position for this hit
3235 pos = origin + dz*dir;
3236
3237 // distance along wire relative to origin
3238 double s = dz/cos(wire->stereo);
3239
3240 if(DEBUG_LEVEL > 15)
3241 cout<<"s="<<s<<" ring="<<wire->ring<<" straw="<<wire->straw<<" stereo="<<wire->stereo<<endl;
3242
3243 // Compute phi for the stereo wire
3244 DVector2 R(fit->x0, fit->y0);
3245 locPhiStereo = atan2(pos.Y() - R.Y(), pos.X() - R.X());
3246 R *= -1.0; // make R point from center of circle to beamline instead of other way around
3247 locPhiStereo -= R.Phi(); // make angle relative to beamline
3248
3249 // We want this to go either from 0 to +2pi for positive charge, or 0 to -2pi for negative.
3250 double phi_hi = fit->h > 0.0 ? +M_TWO_PI6.28318530717958647692 : 0.0;
3251 double phi_lo = fit->h > 0.0 ? 0.0 : -M_TWO_PI6.28318530717958647692;
3252 while(locPhiStereo < phi_lo)
3253 locPhiStereo += M_TWO_PI6.28318530717958647692;
3254 while(locPhiStereo > phi_hi)
3255 locPhiStereo -= M_TWO_PI6.28318530717958647692;
3256
3257 return true;
3258}
3259
3260//--------------------------
3261// Select_CDCSuperLayerSeeds
3262//--------------------------
3263bool DTrackCandidate_factory_CDC::Select_CDCSuperLayerSeeds(DCDCTrackCircle* locCDCTrackCircle, bool locFinalPassFlag)
3264{
3265 // If on initial pass (locFinalPassFlag = false):
3266 // Calculates the theta/z of the track for each possible combination of stereo super layer seeds.
3267 // The combination with the smallest chisq/ndf is selected, and the rest of the super layer seeds are deleted.
3268 // If there are no stereo hits, DO NOT reject the track, as Add_UnusedHits hasn't been called yet, and may find some.
3269
3270 // If on final pass (locFinalPassFlag = true):
3271 // Calculate the theta/z of the track using a subset of the remaining stereo hits
3272 // A subset is used to give the best-possible calculation of theta/z by ignoring hits where the circle-fit may be inaccurate
3273 // This is because the projection of the stereo hits onto the circle may be bad in this region, giving a bad theta/z result
3274 // If there are no stereo hits, reject the track.
3275
3276 // Select the best combinations of stereo hits and determine theta/z
3277 double locBestTheta = 0.0, locBestZ = TARGET_Z, locBestChiSqPerNDF = 9.9E99;
3278 deque<DCDCSuperLayerSeed*> locBestSuperLayerSeeds_Inner;
3279 deque<DCDCSuperLayerSeed*> locBestSuperLayerSeeds_Outer;
3280 bool locGoodStereoComboFoundFlag = false;
3281
3282 if((!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty()) && (!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty()))
3283 {
3284 //hits in both the inner & outer stereo super layers
3285 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
3286 {
3287 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_j)
3288 {
3289 //get the hits from this inner combination
3290 deque<DCDCTrkHit*> locComboHits;
3291 Select_ThetaZStereoHits(locCDCTrackCircle, loc_i, loc_j, locFinalPassFlag, locComboHits);
3292
3293 //Evaluate theta & z for this combination, returning the chisq/ndf from the fit
3294 double locTheta = 0.0, locZ = TARGET_Z, locChiSqPerNDF = 9.9E50;
3295 if(DEBUG_LEVEL > 5)
3296 cout << "in/out try theta/z, num stereo hits = " << locComboHits.size() << endl;
3297 if(!Find_ThetaZ(locCDCTrackCircle->fit, locComboHits, locTheta, locZ, locChiSqPerNDF))
3298 continue; //combo didn't work for some reason, try a different one
3299 if(!((locChiSqPerNDF < 1.0) || (locChiSqPerNDF > -1.0)))
3300 continue; // NaN
3301 locGoodStereoComboFoundFlag = true;
3302 if(DEBUG_LEVEL > 5)
3303 cout << "in/out good theta/z: theta, z, chisq, best-chisq = " << locTheta << ", " << locZ << ", " << locChiSqPerNDF << ", " << locBestChiSqPerNDF << endl;
3304 if(locChiSqPerNDF >= locBestChiSqPerNDF)
3305 continue;
3306 // This is the best combination of stereo seeds so far, save the results
3307 locBestSuperLayerSeeds_Inner.clear();
3308 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i].size(); ++loc_k)
3309 locBestSuperLayerSeeds_Inner.push_back(locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_k]);
3310 locBestSuperLayerSeeds_Outer.clear();
3311 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j].size(); ++loc_k)
3312 locBestSuperLayerSeeds_Outer.push_back(locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j][loc_k]);
3313 locBestTheta = locTheta;
3314 locBestZ = locZ;
3315 locBestChiSqPerNDF = locChiSqPerNDF;
3316 }
3317 }
3318 }
3319 else if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
3320 {
3321 //no hits in the outer super layers (or super layer 4 was missing)
3322 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
3323 {
3324 //get the hits from this inner combination
3325 deque<DCDCTrkHit*> locComboHits;
3326 Select_ThetaZStereoHits(locCDCTrackCircle, loc_i, -1, locFinalPassFlag, locComboHits);
3327
3328 //Evaluate theta & z for this combination, returning the chisq/ndf from the fit
3329 double locTheta = 0.0, locZ = TARGET_Z, locChiSqPerNDF = 9.9E50;
3330 if(DEBUG_LEVEL > 5)
3331 cout << "in-only try theta/z, num stereo hits = " << locComboHits.size() << endl;
3332 if(!Find_ThetaZ(locCDCTrackCircle->fit, locComboHits, locTheta, locZ, locChiSqPerNDF))
3333 continue; //combo didn't work for some reason, try a different one
3334 if(!((locChiSqPerNDF < 1.0) || (locChiSqPerNDF > -1.0)))
3335 continue; // NaN
3336 locGoodStereoComboFoundFlag = true;
3337 if(DEBUG_LEVEL > 5)
3338 cout << "in-only good theta/z: theta, z, chisq, best-chisq = " << locTheta << ", " << locZ << ", " << locChiSqPerNDF << ", " << locBestChiSqPerNDF << endl;
3339 if(locChiSqPerNDF >= locBestChiSqPerNDF)
3340 continue;
3341 // This is the best combination of stereo seeds so far, save the results
3342 locBestSuperLayerSeeds_Inner.clear();
3343 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i].size(); ++loc_k)
3344 locBestSuperLayerSeeds_Inner.push_back(locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_k]);
3345 locBestSuperLayerSeeds_Outer.clear();
3346 locBestTheta = locTheta;
3347 locBestZ = locZ;
3348 locBestChiSqPerNDF = locChiSqPerNDF;
3349 }
3350 }
3351 else if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
3352 {
3353 // no hits in the inner super layers: e.g. decay product (e.g. p) of a long-lived decaying neutral particle (e.g. lambda)
3354 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_j)
3355 {
3356 //get the hits from this inner combination
3357 deque<DCDCTrkHit*> locComboHits;
3358 Select_ThetaZStereoHits(locCDCTrackCircle, -1, loc_j, locFinalPassFlag, locComboHits);
3359
3360 //Evaluate theta & z for this combination, returning the chisq/ndf from the fit
3361 double locTheta = 0.0, locZ = TARGET_Z, locChiSqPerNDF = 9.9E50;
3362 if(DEBUG_LEVEL > 5)
3363 cout << "out-only try theta/z, num stereo hits = " << locComboHits.size() << endl;
3364 if(!Find_ThetaZ(locCDCTrackCircle->fit, locComboHits, locTheta, locZ, locChiSqPerNDF))
3365 continue; //combo didn't work for some reason, try a different one
3366 if(!((locChiSqPerNDF < 1.0) || (locChiSqPerNDF > -1.0)))
3367 continue; // NaN
3368 locGoodStereoComboFoundFlag = true;
3369 if(DEBUG_LEVEL > 5)
3370 cout << "out-only good theta/z: theta, z, chisq, best-chisq = " << locTheta << ", " << locZ << ", " << locChiSqPerNDF << ", " << locBestChiSqPerNDF << endl;
3371 if(locChiSqPerNDF >= locBestChiSqPerNDF)
3372 continue;
3373 // This is the best combination of stereo seeds so far, save the results
3374 locBestSuperLayerSeeds_Inner.clear();
3375 locBestSuperLayerSeeds_Outer.clear();
3376 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j].size(); ++loc_k)
3377 locBestSuperLayerSeeds_Outer.push_back(locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j][loc_k]);
3378 locBestTheta = locTheta;
3379 locBestZ = locZ;
3380 locBestChiSqPerNDF = locChiSqPerNDF;
3381 }
3382 }
3383 else //no stereo hits
3384 return (!locFinalPassFlag); //return true if don't wan't to filter, false if you do
3385
3386 //save the results to the track circle
3387 locCDCTrackCircle->dTheta = locBestTheta;
3388 locCDCTrackCircle->dVertexZ = locBestZ;
3389 double locNumStereoSuperLayers = double(locBestSuperLayerSeeds_Inner.size() + locBestSuperLayerSeeds_Outer.size());
3390 locCDCTrackCircle->dWeightedChiSqPerDF_Stereo = locBestChiSqPerNDF/(locNumStereoSuperLayers*locNumStereoSuperLayers);
3391
3392 set<DCDCSuperLayerSeed*> locAlreadyRecycledSuperLayerSeeds; //a seed can appear in more than one combo: don't recycle the same memory more than once!!
3393
3394 // recycle the unused super layer seeds and store only the best ones: inner
3395 if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
3396 {
3397 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
3398 {
3399 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i].size(); ++loc_j)
3400 {
3401 DCDCSuperLayerSeed* locCDCSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_j];
3402 if(locAlreadyRecycledSuperLayerSeeds.find(locCDCSuperLayerSeed) != locAlreadyRecycledSuperLayerSeeds.end())
3403 continue; //already recycled!
3404 bool locKeepSuperLayerSeed = false;
3405 for(size_t loc_k = 0; loc_k < locBestSuperLayerSeeds_Inner.size(); ++loc_k)
3406 {
3407 if(locBestSuperLayerSeeds_Inner[loc_k] != locCDCSuperLayerSeed)
3408 continue;
3409 locKeepSuperLayerSeed = true; //one of the best, don't recycle!!
3410 break;
3411 }
3412 if(locKeepSuperLayerSeed)
3413 continue;
3414 Recycle_DCDCSuperLayerSeed(locCDCSuperLayerSeed); //no longer in use
3415 locAlreadyRecycledSuperLayerSeeds.insert(locCDCSuperLayerSeed);
3416 }
3417 }
3418 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.clear();
3419 if(locGoodStereoComboFoundFlag)
3420 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(locBestSuperLayerSeeds_Inner);
3421 }
3422 locAlreadyRecycledSuperLayerSeeds.clear();
3423
3424 // recycle the unused super layer seeds and store only the best ones: outer
3425 if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
3426 {
3427 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_i)
3428 {
3429 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i].size(); ++loc_j)
3430 {
3431 DCDCSuperLayerSeed* locCDCSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i][loc_j];
3432 if(locAlreadyRecycledSuperLayerSeeds.find(locCDCSuperLayerSeed) != locAlreadyRecycledSuperLayerSeeds.end())
3433 continue; //already recycled!
3434 bool locKeepSuperLayerSeed = false;
3435 for(size_t loc_k = 0; loc_k < locBestSuperLayerSeeds_Outer.size(); ++loc_k)
3436 {
3437 if(locBestSuperLayerSeeds_Outer[loc_k] != locCDCSuperLayerSeed)
3438 continue;
3439 locKeepSuperLayerSeed = true; //one of the best, don't recycle!!
3440 break;
3441 }
3442 if(locKeepSuperLayerSeed)
3443 continue;
3444 Recycle_DCDCSuperLayerSeed(locCDCSuperLayerSeed); //no longer in use
3445 locAlreadyRecycledSuperLayerSeeds.insert(locCDCSuperLayerSeed);
3446 }
3447 }
3448 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.clear();
3449 if(locGoodStereoComboFoundFlag)
3450 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(locBestSuperLayerSeeds_Outer);
3451 }
3452
3453 return locGoodStereoComboFoundFlag;
3454}
3455
3456//------------------------
3457// Select_ThetaZStereoHits
3458//------------------------
3459void DTrackCandidate_factory_CDC::Select_ThetaZStereoHits(const DCDCTrackCircle* locCDCTrackCircle, int locInnerSeedSeriesIndex, int locOuterSeedSeriesIndex, bool locFinalPassFlag, deque<DCDCTrkHit*>& locComboHits)
3460{
3461 //tracks at the edges of the CDC's phase space OFTEN fail because the circle-fit is not perfect
3462 //this causes the projected-hit-position on the circle of the stereo hits to be incorrect
3463 //which then causes the calculated theta/z to be bad, which causes the momentum magnitude to be bad
3464 //this is especially a concern for tracks without hits in Super Layer (SL) 7: e.g. spiraling tracks in SL6 or tracks leaving the CDC
3465 //this is because the circle fit is extrapolated out to SL5 & SL6 and the errors are much larger
3466 //therefore, you must be VERY careful when selecting which stereo hits to use for the final calculation of theta & z
3467 //for the initial calculation: use all stereo hits: the initial calculation is intended to select which stereo super layer seeds are best, nothing more
3468
3469 locComboHits.clear();
3470
3471 // Get super layer seeds for this combination
3472 deque<DCDCSuperLayerSeed*> locSuperLayerSeeds;
3473 if(locInnerSeedSeriesIndex >= 0)
3474 {
3475 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[locInnerSeedSeriesIndex].size(); ++loc_k)
3476 locSuperLayerSeeds.push_back(locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[locInnerSeedSeriesIndex][loc_k]);
3477 }
3478 if(locOuterSeedSeriesIndex >= 0)
3479 {
3480 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[locOuterSeedSeriesIndex].size(); ++loc_k)
3481 locSuperLayerSeeds.push_back(locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[locOuterSeedSeriesIndex][loc_k]);
3482 }
3483
3484 //select initial hits: prune hits that don't intersect the circle
3485 deque<DCDCTrkHit*> locHits;
3486 map<unsigned int, deque<DCDCTrkHit*> > locHitsBySuperLayer; //key is super layer
3487 unsigned int locTotalNumStereoHits = 0;
3488 for(size_t loc_k = 0; loc_k < locSuperLayerSeeds.size(); ++loc_k)
3489 {
3490 locSuperLayerSeeds[loc_k]->Get_Hits(locHits);
3491 for(deque<DCDCTrkHit*>::iterator locIterator = locHits.begin(); locIterator != locHits.end();)
3492 {
3493 if((*locIterator)->dValidStereoHitPosFlag)
3494 ++locIterator;
3495 else
3496 locIterator = locHits.erase(locIterator);
3497 }
3498 locHitsBySuperLayer[locSuperLayerSeeds[loc_k]->dSuperLayer] = locHits;
3499 locTotalNumStereoHits += locHits.size();
3500 }
3501
3502 // see if no more pruning is necessary
3503 // don't prune anymore if on initial pass, or if very few stereo hits
3504 if((!locFinalPassFlag) || (locTotalNumStereoHits <= MIN_PRUNED_STEREO_HITS))
3505 {
3506 // no more pruning, add hits to locComboHits and return
3507 map<unsigned int, deque<DCDCTrkHit*> >::iterator locMapIterator;
3508 for(locMapIterator = locHitsBySuperLayer.begin(); locMapIterator != locHitsBySuperLayer.end(); ++locMapIterator)
3509 locComboHits.insert(locComboHits.end(), locMapIterator->second.begin(), locMapIterator->second.end());
3510 if(DEBUG_LEVEL > 10)
3511 cout << "no more pruning, total num stereo hits = " << locTotalNumStereoHits << endl;
3512 return; //either on first pass (eval'ing which stereo seed is best), or not enough hits to prune: return
3513 }
3514
3515 // Now, select the stereo hits whose projection onto the cirlce-fit are closest to the axial hits
3516 // the closer the stereo hits are to the axial hits, the better the estimation of theta/z will be
3517
3518 //calc delta-phi for all remaining hits and sort them
3519 //delta-phi: between the intersection-of-the-stereo-hit-with-the-circle and the nearest axial hits
3520 deque<pair<DCDCTrkHit*, double> > locDeltaPhis;
3521 for(size_t loc_k = 0; loc_k < locSuperLayerSeeds.size(); ++loc_k)
3522 {
3523 unsigned int locSuperLayer = locSuperLayerSeeds[loc_k]->dSuperLayer;
3524 Calc_StereoHitDeltaPhis(locSuperLayer, locHitsBySuperLayer[locSuperLayer], locCDCTrackCircle, locDeltaPhis);
3525 }
3526 sort(locDeltaPhis.begin(), locDeltaPhis.end(), CDCSort_DeltaPhis);
3527
3528 if(locDeltaPhis.size() <= MIN_PRUNED_STEREO_HITS)
3529 {
3530 for(size_t loc_k = 0; loc_k < locDeltaPhis.size(); ++loc_k)
3531 locComboHits.push_back(locDeltaPhis[loc_k].first);
3532 return;
3533 }
3534
3535 // take at least the "MIN_PRUNED_STEREO_HITS" hits with the smallest delta_phi
3536 double locMaxHitDeltaPhi = locDeltaPhis[MIN_PRUNED_STEREO_HITS - 1].second;
3537
3538 // now, potentially expand the max-delta-phi range in certain cases:
3539 double locDeltaPhiRangeExtension = 0.0;
3540 //if first statement below is true, want all the stereo hits:
3541 //track was matched to another track circle as a spiral turn, and it turns in its last axial layer (4 or 7)
3542 //because it is turning sharply, as much info/hits as possible is needed to give an accurate theta
3543 //however, if it was turning in a stereo layer, then the sharpest part of the turn was not included in the circle fit
3544 //in this case the hit-projections onto the circle are probably way off, so only expand to pi if turning on axial layer
3545 //if second statement below is true, then the track was very unlikely to spiral, because the radius of the circle indicates it (likely) passed through the bcal
3546 //in this case, all stereo hits within a reasonable distance (10 degrees) from the track circle are probably OK.
3547 //note: expanding beyond 10-15 degrees kills candidates at theta >= 120:
3548 //these tracks leave the CDC at SL6 and sooner, and extrapolating the circle fit out to SL6 gives spurious results, so truncate the theta-search
3549 //if neither statement below is true, then the track likely spiraled in a stereo super layer:
3550 //don't trust the stereo information as much: only take stereo hits very close to the axial hits
3551
3552 unsigned int locLastSuperLayer = locCDCTrackCircle->Get_LastSuperLayerSeed()->dSuperLayer;
3553 if(((locLastSuperLayer == 4) || (locLastSuperLayer == 7)) && (locCDCTrackCircle->dSpiralTurnRing != -1))
3554 locDeltaPhiRangeExtension = M_PI3.14159265358979323846; //spiral turn on axial layer: all stereo hits good
3555 else if(locCDCTrackCircle->fit->r0 > 65.0/2.0) //BCAL is at r = ~65
3556 locDeltaPhiRangeExtension = 10.0; //unlikely to spiral, all stereo hits reasonably close are good
3557 else
3558 locDeltaPhiRangeExtension = 5.0; //likely spiraled, trust stereo information less
3559 locMaxHitDeltaPhi += locDeltaPhiRangeExtension;
3560
3561 if(DEBUG_LEVEL > 10)
3562 cout << "prune with max delta-phi, fit circle r0 = " << locMaxHitDeltaPhi << ", " << locCDCTrackCircle->fit->r0 << endl;
3563 size_t locDeltaPhiIndex = 0;
3564 // add stereo hits to locComboHits whose projection onto the circle fit are within locMaxHitDeltaPhi of the nearest axial hit phi
3565 for(locDeltaPhiIndex = 0; locDeltaPhiIndex < locDeltaPhis.size(); ++locDeltaPhiIndex)
3566 {
3567 if(locDeltaPhis[locDeltaPhiIndex].second > locMaxHitDeltaPhi)
3568 break;
3569 locComboHits.push_back(locDeltaPhis[locDeltaPhiIndex].first);
3570 }
3571
3572 //make sure to have at least one wire from each super layer
3573 // this is especially useful for spiral turns in SL6, where the majority of the theta-constraining information comes from SL5 and SL6
3574 // you don't want very many of these hits because they can throw you off, but having at least one really helps
3575 // this is experimental: it may not be necessary if the above locMaxHitDeltaPhi section is better fine-tuned
3576
3577 // to keep track of which super layers need hits, delete keys from locHitsBySuperLayer map if hits from them are already selected
3578 map<unsigned int, deque<DCDCTrkHit*> >::iterator locMapIterator;
3579 for(size_t loc_i = 0; loc_i < locComboHits.size(); ++loc_i)
3580 {
3581 unsigned int locSuperLayer = (locComboHits[loc_i]->hit->wire->ring - 1)/4 + 1;
3582 locMapIterator = locHitsBySuperLayer.find(locSuperLayer);
3583 if(locMapIterator == locHitsBySuperLayer.end())
3584 continue; //already have a hit of that type
3585 locHitsBySuperLayer.erase(locMapIterator); //have a hit of this type
3586 if(locHitsBySuperLayer.empty())
3587 break;
3588 }
3589
3590 //locHitsBySuperLayer now only contains the keys of super layers that don't have hits yet: loop over them
3591 for(locMapIterator = locHitsBySuperLayer.begin(); locMapIterator != locHitsBySuperLayer.end(); ++locMapIterator)
3592 {
3593 // search for the hit with the lowest delta-phi from this (locMapIterator->first) super layer
3594 for(size_t loc_i = locDeltaPhiIndex; loc_i < locDeltaPhis.size(); ++loc_i) //everything before locDeltaPhiIndex was already included
3595 {
3596 unsigned int locSuperLayer = (locDeltaPhis[loc_i].first->hit->wire->ring - 1)/4 + 1;
3597 if(locSuperLayer != locMapIterator->first)
3598 continue;
3599 locComboHits.push_back(locDeltaPhis[loc_i].first); //use best hit on this super layer
3600 if(DEBUG_LEVEL > 10)
3601 cout << "Add stereo hit on SL" << locSuperLayer << ": ring, straw = " << locDeltaPhis[loc_i].first->hit->wire->ring << ", " << locDeltaPhis[loc_i].first->hit->wire->straw << endl;
3602 break;
3603 }
3604 }
3605
3606 if(DEBUG_LEVEL > 10)
3607 cout << "final #hits = " << locComboHits.size() << endl;
3608}
3609
3610//------------------------
3611// Calc_StereoHitDeltaPhis
3612//------------------------
3613void DTrackCandidate_factory_CDC::Calc_StereoHitDeltaPhis(unsigned int locSuperLayer, deque<DCDCTrkHit*>& locHits, const DCDCTrackCircle* locCDCTrackCircle, deque<pair<DCDCTrkHit*, double> >& locDeltaPhis)
3614{
3615 // calc delta-phi for hits: distance from projected-stereo-hit-position to the nearest axial hits
3616 // because the circle fit is not perfect, the stereo hit position gets progessively worse the sharper the track is turning
3617 // this screws up the theta/z calculation, so just ignore the hits that are the farthest away
3618 // don't do this unless on the final pass though: even a moderately bad theta/z is (in theory) still good enough for vetoing totally wrong hit combinations
3619
3620 if(DEBUG_LEVEL > 10)
3621 cout << "Calc_StereoHitDeltaPhis, SL = " << locSuperLayer << ", #hits = " << locHits.size() << endl;
3622
3623 //get the axial super layer seeds nearest this seed:
3624 DCDCSuperLayerSeed* locPriorAxialSuperLayerSeed = NULL__null;
3625 DCDCSuperLayerSeed* locNextAxialSuperLayerSeed = NULL__null;
3626 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_k)
3627 {
3628 if(locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_k]->dSuperLayer < locSuperLayer)
3629 locPriorAxialSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_k];
3630 else if((locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_k]->dSuperLayer > locSuperLayer) && (locNextAxialSuperLayerSeed == NULL__null))
3631 locNextAxialSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_k];
3632 }
3633
3634 //get the rings in the axial super layer seeds nearest this stereo seed:
3635 DCDCRingSeed* locPriorAxialRingSeed = NULL__null;
3636 if(locPriorAxialSuperLayerSeed != NULL__null)
3637 {
3638 locPriorAxialRingSeed = &(locPriorAxialSuperLayerSeed->dCDCRingSeeds.back());
3639 if(DEBUG_LEVEL > 10)
3640 cout << "Prior axial ring = " << locPriorAxialRingSeed->ring << endl;
3641 }
3642 DCDCRingSeed* locNextAxialRingSeed = NULL__null;
3643 if(locNextAxialSuperLayerSeed != NULL__null)
3644 {
3645 locNextAxialRingSeed = &(locNextAxialSuperLayerSeed->dCDCRingSeeds.front());
3646 if(DEBUG_LEVEL > 10)
3647 cout << "Next axial ring = " << locNextAxialRingSeed->ring << endl;
3648 }
3649 if((locPriorAxialRingSeed == NULL__null) && (locNextAxialRingSeed == NULL__null))
3650 return; //no axial hits: shoudldn't be possible ...
3651
3652 // calculate min-delta-phi for each hit (to the nearest axial ring seed)
3653 for(size_t loc_i = 0; loc_i < locHits.size(); ++loc_i)
3654 {
3655 deque<DCDCTrkHit*> locTempDeque(1, locHits[loc_i]);
3656 double locMinDeltaPhi = M_PI3.14159265358979323846;
3657 //compare to prior axial ring
3658 if(locPriorAxialRingSeed != NULL__null)
3659 {
3660 double locDeltaPhi = MinDeltaPhi(locPriorAxialRingSeed->hits, locTempDeque);
3661 if(locDeltaPhi < locMinDeltaPhi)
3662 locMinDeltaPhi = locDeltaPhi;
3663 }
3664 //compare to next axial ring
3665 if(locNextAxialRingSeed != NULL__null)
3666 {
3667 double locDeltaPhi = MinDeltaPhi(locTempDeque, locNextAxialRingSeed->hits);
3668 if(locDeltaPhi < locMinDeltaPhi)
3669 locMinDeltaPhi = locDeltaPhi;
3670 }
3671 locMinDeltaPhi *= 180.0/M_PI3.14159265358979323846;
3672 if(DEBUG_LEVEL > 10)
3673 cout << "Ring, Straw, min delta phi = " << locHits[loc_i]->hit->wire->ring << ", " << locHits[loc_i]->hit->wire->straw << ", " << locMinDeltaPhi << endl;
3674 //store the minimum
3675 locDeltaPhis.push_back(pair<DCDCTrkHit*, double>(locHits[loc_i], locMinDeltaPhi));
3676 }
3677}
3678
3679//------------
3680// MinDeltaPhi
3681//------------
3682double DTrackCandidate_factory_CDC::MinDeltaPhi(const deque<DCDCTrkHit*>& locInnerSeedHits, const deque<DCDCTrkHit*>& locOuterSeedHits)
3683{
3684 /// Returns the minimum delta-phi between the two groups of hits. Assumes all of the hits in a given set are on the same ring.
3685 /// First it checks if the two seeds overlap in phi: if so, then return 0
3686 /// Otherwise, only the first and last hits of the adjacent rings between each seed's hit list are used.
3687 /// to calculate a maximum of 4 delta-phis (minimum of 1) of which, the smallest is returned.
3688 if(locInnerSeedHits.empty() || locOuterSeedHits.empty())
3689 {
3690 cout << "Number of seed hits 0! (Ninner = " << locInnerSeedHits.size() << " ,Nouter = " << locOuterSeedHits.size() << ")" << endl;
3691 return M_PI3.14159265358979323846;
3692 }
3693
3694 DCDCTrkHit* locInnermostRingFirstStrawHit = locInnerSeedHits.front();
3695 DCDCTrkHit* locInnermostRingLastStrawHit = locInnerSeedHits.back();
3696 DCDCTrkHit* locOutermostRingFirstStrawHit = locOuterSeedHits.front();
3697 DCDCTrkHit* locOutermostRingLastStrawHit = locOuterSeedHits.back();
3698
3699 //see if seeds overlap in phi
3700 float locInnermostRingFirstStrawPhi = locInnermostRingFirstStrawHit->hit->wire->phi;
3701 float locInnermostRingLastStrawPhi = locInnermostRingLastStrawHit->hit->wire->phi;
3702 float locOutermostRingFirstStrawPhi = locOutermostRingFirstStrawHit->hit->wire->phi;
3703 float locOutermostRingLastStrawPhi = locOutermostRingLastStrawHit->hit->wire->phi;
3704 if(DEBUG_LEVEL > 100)
3705 cout << "inner ring: ring, first/last straws & phis = " << locInnermostRingFirstStrawHit->hit->wire->ring << ", " << locInnermostRingFirstStrawHit->hit->wire->straw << ", " << locInnermostRingLastStrawHit->hit->wire->straw << ", " << locInnermostRingFirstStrawPhi << ", " << locInnermostRingLastStrawPhi << endl;
3706 if(DEBUG_LEVEL > 100)
3707 cout << "outer ring: ring, first/last straws & phis = " << locOutermostRingFirstStrawHit->hit->wire->ring << ", " << locOutermostRingFirstStrawHit->hit->wire->straw << ", " << locOutermostRingLastStrawHit->hit->wire->straw << ", " << locOutermostRingFirstStrawPhi << ", " << locOutermostRingLastStrawPhi << endl;
3708
3709 //account for phi = 0/2pi boundary
3710 bool locInnerRingCrossesBoundaryFlag = (locInnermostRingLastStrawPhi < locInnermostRingFirstStrawPhi);
3711 bool locOuterRingCrossesBoundaryFlag = (locOutermostRingLastStrawPhi < locOutermostRingFirstStrawPhi);
3712 if(DEBUG_LEVEL > 100)
3713 cout << "in/out boundary flags = " << locInnerRingCrossesBoundaryFlag << ", " << locOuterRingCrossesBoundaryFlag << endl;
3714 if(locOuterRingCrossesBoundaryFlag)
3715 locOutermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
3716 if(locInnerRingCrossesBoundaryFlag)
3717 locInnermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
3718 if(locOuterRingCrossesBoundaryFlag & (!locInnerRingCrossesBoundaryFlag) && ((locOutermostRingLastStrawPhi - locInnermostRingLastStrawPhi) > M_PI3.14159265358979323846))
3719 {
3720 locInnermostRingFirstStrawPhi += M_TWO_PI6.28318530717958647692;
3721 locInnermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
3722 }
3723 if(locInnerRingCrossesBoundaryFlag & (!locOuterRingCrossesBoundaryFlag) && ((locInnermostRingLastStrawPhi - locOutermostRingLastStrawPhi) > M_PI3.14159265358979323846))
3724 {
3725 locOutermostRingFirstStrawPhi += M_TWO_PI6.28318530717958647692;
3726 locOutermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
3727 }
3728
3729 if(DEBUG_LEVEL > 100)
3730 cout << "final inner ring: ring, first/last straws & phis = " << locInnermostRingFirstStrawHit->hit->wire->ring << ", " << locInnermostRingFirstStrawHit->hit->wire->straw << ", " << locInnermostRingLastStrawHit->hit->wire->straw << ", " << locInnermostRingFirstStrawPhi << ", " << locInnermostRingLastStrawPhi << endl;
3731 if(DEBUG_LEVEL > 100)
3732 cout << "final outer ring: ring, first/last straws & phis = " << locOutermostRingFirstStrawHit->hit->wire->ring << ", " << locOutermostRingFirstStrawHit->hit->wire->straw << ", " << locOutermostRingLastStrawHit->hit->wire->straw << ", " << locOutermostRingFirstStrawPhi << ", " << locOutermostRingLastStrawPhi << endl;
3733
3734 if((locOutermostRingFirstStrawPhi >= locInnermostRingFirstStrawPhi) && (locOutermostRingFirstStrawPhi <= locInnermostRingLastStrawPhi))
3735 return 0.0;
3736 if((locOutermostRingLastStrawPhi >= locInnermostRingFirstStrawPhi) && (locOutermostRingLastStrawPhi <= locInnermostRingLastStrawPhi))
3737 return 0.0;
3738 if((locInnermostRingFirstStrawPhi >= locOutermostRingFirstStrawPhi) && (locInnermostRingFirstStrawPhi <= locOutermostRingLastStrawPhi))
3739 return 0.0; //4th case not needed. this case only needed if innermost ring is one wire across
3740
3741 //make all 4 comparisons between hits
3742 double locDeltaPhi, locMinDeltaPhi;
3743 locMinDeltaPhi = fabs(locInnermostRingFirstStrawPhi - locOutermostRingFirstStrawPhi);
3744 if(locMinDeltaPhi > M_PI3.14159265358979323846)
3745 locMinDeltaPhi = fabs(locMinDeltaPhi - M_TWO_PI6.28318530717958647692);
3746 if(locOutermostRingFirstStrawHit != locOutermostRingLastStrawHit)
3747 {
3748 locDeltaPhi = fabs(locInnermostRingFirstStrawPhi - locOutermostRingLastStrawPhi);
3749 if(locDeltaPhi > M_PI3.14159265358979323846)
3750 locDeltaPhi = fabs(locDeltaPhi - M_TWO_PI6.28318530717958647692);
3751 if(locDeltaPhi < locMinDeltaPhi)
3752 locMinDeltaPhi = locDeltaPhi;
3753 }
3754 if(locInnermostRingFirstStrawHit == locInnermostRingLastStrawHit)
3755 return locMinDeltaPhi;
3756
3757 locDeltaPhi = fabs(locInnermostRingLastStrawPhi - locOutermostRingFirstStrawPhi);
3758 if(locDeltaPhi > M_PI3.14159265358979323846)
3759 locDeltaPhi = fabs(locDeltaPhi - M_TWO_PI6.28318530717958647692);
3760 if(locDeltaPhi < locMinDeltaPhi)
3761 locMinDeltaPhi = locDeltaPhi;
3762 if(locOutermostRingFirstStrawHit != locOutermostRingLastStrawHit)
3763 {
3764 locDeltaPhi = fabs(locInnermostRingLastStrawPhi - locOutermostRingLastStrawPhi);
3765 if(locDeltaPhi > M_PI3.14159265358979323846)
3766 locDeltaPhi = fabs(locDeltaPhi - M_TWO_PI6.28318530717958647692);
3767 if(locDeltaPhi < locMinDeltaPhi)
3768 locMinDeltaPhi = locDeltaPhi;
3769 }
3770
3771 return locMinDeltaPhi;
3772}
3773
3774//------------
3775// Find_ThetaZ
3776//------------
3777bool DTrackCandidate_factory_CDC::Find_ThetaZ(const DHelicalFit* locFit, const deque<DCDCTrkHit*>& locStereoHits, double& locTheta, double& locZ, double& locChiSqPerNDF)
3778{
3779 // Calculate theta/z for the input stereo hits
3780 if(locStereoHits.empty())
3781 return false;
3782
3783 if(Find_ThetaZ_Regression(locFit, locStereoHits, locTheta, locZ, locChiSqPerNDF))
3784 return true;
3785 double locThetaMin, locThetaMax;
3786
3787 // Regression fit failed, try using histogram methods
3788 bool locThetaOKFlag = Find_Theta(locFit, locStereoHits, locTheta, locThetaMin, locThetaMax, locChiSqPerNDF);
3789 if(locThetaOKFlag)
3790 {
3791 if(Find_Z(locFit, locStereoHits, locThetaMin, locThetaMax, locZ))
3792 return true;
3793 }
3794
3795 // Histogram methods failed.
3796
3797 // Assume that the track came from the center of the target
3798 locChiSqPerNDF = 9.9E8;
3799 locZ = TARGET_Z;
3800 if(locThetaOKFlag)
3801 return true;
3802
3803 // Use a point in one of the stereo layers to estimate tanl
3804 double x = locStereoHits[0]->dStereoHitPos.X();
3805 double y = locStereoHits[0]->dStereoHitPos.Y();
3806 double tworc = 2.0*locFit->r0;
3807 double ratio = sqrt(x*x + y*y)/tworc;
3808 if(ratio >= 1.0)
3809 return false;
3810
3811 double tanl = (locStereoHits[0]->dStereoHitPos.Z() - locZ)/(tworc*asin(ratio));
3812 locTheta = M_PI_21.57079632679489661923 - atan(tanl);
3813 return true;
3814}
3815
3816//-----------------------
3817// Find_ThetaZ_Regression
3818//-----------------------
3819// Linear regression to find tan(lambda) and z_vertex.
3820// This method assumes that there are errors in both the z positions and
3821// the arc lengths.
3822// Algorithm from Numerical Recipes in C (2nd. ed.), pp. 668-669.
3823bool DTrackCandidate_factory_CDC::Find_ThetaZ_Regression(const DHelicalFit* locFit, const deque<DCDCTrkHit*>& locStereoHits, double& locTheta, double& locZ, double& locChiSqPerNDF)
3824{
3825 if(DEBUG_LEVEL > 3)
3826 cout<<"Finding theta and z via linear regression method."<<endl;
3827
3828 if(locStereoHits.empty() || (!(locFit->normal.Mag() > 0.0)))
3829 return false;
3830
3831 // Vector of intersections between the circle and the stereo wires
3832 vector<intersection_t> intersections;
3833 for(size_t m = 0; m < locStereoHits.size(); ++m)
3834 {
3835 DCDCTrkHit* trkhit = locStereoHits[m];
3836
3837 //DVector3_with_perp intersection;
3838 intersection_t intersection;
3839 intersection.x = trkhit->dStereoHitPos.X();
3840 intersection.y = trkhit->dStereoHitPos.Y();
3841 intersection.perp2 = intersection.x*intersection.x + intersection.y*intersection.y;
3842 intersection.z = trkhit->dStereoHitPos.Z();
3843 intersection.var_z = trkhit->var_z;
3844 intersections.push_back(intersection);
3845 }
3846
3847 // Now, sort the entries
3848 sort(intersections.begin(), intersections.end(), CDCSort_Intersections);
3849
3850 // Compute the arc lengths between the origin in x and y and (xi,yi)
3851 vector<double> arclengths(intersections.size());
3852 vector<double> ratios(intersections.size());
3853 double xc = locFit->x0;
3854 double yc = locFit->y0;
3855 double rc = locFit->r0;
3856 double two_rc = 2.*rc;
3857
3858 // Find POCA to beam line
3859 double myphi = atan2(yc, xc);
3860 double y0 = yc - rc*sin(myphi);
3861 double x0 = xc - rc*cos(myphi);
3862
3863 // Arc length to first measurement
3864 double diffx = intersections[0].x - x0;
3865 double diffy = intersections[0].y - y0;
3866 double chord = sqrt(diffx*diffx + diffy*diffy);
3867 double ratio = chord/two_rc;
3868 double s = (ratio < 1.) ? two_rc*asin(ratio) : M_PI_21.57079632679489661923*two_rc;
3869 arclengths[0] = s;
3870 ratios[0] = ratio;
3871
3872 // Find arc lengths for the rest of the stereo hits
3873 for(size_t m = 1; m < arclengths.size(); ++m)
3874 {
3875 diffx = intersections[m].x - intersections[m - 1].x;
3876 diffy = intersections[m].y - intersections[m - 1].y;
3877 chord = sqrt(diffx*diffx + diffy*diffy);
3878 ratio = chord/two_rc;
3879 if(ratio > 0.999)
3880 return false;
3881 double ds = two_rc*asin(ratio);
3882 s += ds;
3883 arclengths[m] = s;
3884 ratios[m] = ratio;
3885 }
3886
3887 //Linear regression to find z0, tanl
3888 double tanl = 0.,z0 = 0.;
3889 if(arclengths.size() > 1) // Do fit only if have more than one measurement
3890 {
3891 DCDCLineFit fit;
3892 size_t n = fit.n = intersections.size();
3893 fit.s.resize(n);
3894 fit.var_s.resize(n);
3895 fit.z.resize(n);
3896 fit.var_z.resize(n);
3897 fit.w.resize(n);
3898
3899 // Find average variances for z and s
3900 double avg_var_s = 0., avg_var_z = 0.;
3901 double var_r = 1.6*1.6/12.; // assume cell size
3902 for (size_t m = 0; m < n; ++m)
3903 {
3904 fit.s[m] = arclengths[m];
3905 fit.var_s[m] = var_r/(1. - ratios[m]*ratios[m]);
3906
3907 avg_var_s += fit.var_s[m];
3908 avg_var_z += intersections[m].var_z;
3909
3910 if(DEBUG_LEVEL>5)
3911 cout<<"Using CDC hit "<<m<<" z="<<intersections[m].z << " s=" << arclengths[m] <<endl;
3912 }
3913
3914 // Scale z errors according to the ratio of the average variances
3915 double scale2 = avg_var_s/avg_var_z;
3916 double scale = sqrt(scale2);
3917 vector<double> weight(n);
3918 for (size_t m = 0; m < n; ++m)
3919 {
3920 fit.z[m] = scale*intersections[m].z;
3921 fit.var_z[m] = scale2*intersections[m].var_z;
3922 weight[m] = fit.var_s[m] + fit.var_z[m];
3923 }
3924
3925 // Perform preliminary fit to find the (scaled) slope tanl
3926 double sumv=0., sumx=0.;
3927 double sumy=0., sumxx=0., sumxy=0.;
3928 for(size_t m = 0; m < n; ++m)
3929 {
3930 //double temp = 1./var_z[m];
3931 double temp = 1./weight[m];
3932 sumv += temp;
3933 sumx += arclengths[m]*temp;
3934 sumy += fit.z[m]*temp;
3935 sumxx += arclengths[m]*arclengths[m]*temp;
3936 sumxy += arclengths[m]*fit.z[m]*temp;
3937 }
3938 double Delta = sumv*sumxx - sumx*sumx;
3939 if(!(fabs(Delta) > 0.0))
3940 return false;
3941
3942 tanl = (sumv*sumxy - sumx*sumy)/Delta;
3943 fit.z0 = (sumxx*sumy - sumx*sumxy)/Delta;
3944
3945 // Convert tanl to an angle and create two other reference angles
3946 double angle[3];
3947 angle[0] = 0.;
3948 angle[1] = atan(tanl);
3949 angle[2] = 1.571;
3950 // Compute chi^2 values for line fits with these three angles
3951 double ch[3];
3952 for (unsigned int m = 0; m < 3; ++m)
3953 ch[m] = fit.ChiXY(angle[m]);
3954
3955 // Bracket the minimum chi^2
3956 fit.BracketMinimumChisq(angle[0], angle[1], angle[2], ch[0], ch[1], ch[2]);
3957 // Find the minimum chi^2 using Brent's method and compute the best value for lambda
3958 double lambda = 0.;
3959 locChiSqPerNDF = fit.FindMinimumChisq(angle[0], angle[1], angle[2], lambda)/2.0; //2 degrees of freedom
3960 // Undo the scaling
3961 z0 = fit.z0/scale;
3962 tanl = tan(lambda)/scale;
3963 }
3964 else
3965 {
3966 z0 = TARGET_Z;
3967 tanl = (intersections[0].z - z0)/arclengths[0];
3968 locChiSqPerNDF = 9.9E9; //only two hits: technically is zero, but if possible want to pick a group of stereo hits with more hits
3969 }
3970
3971 locTheta = M_PI_21.57079632679489661923 - atan(tanl);
3972 locZ = z0;
3973
3974 return true;
3975}
3976
3977//-----------
3978// Find_Theta
3979//-----------
3980bool DTrackCandidate_factory_CDC::Find_Theta(const DHelicalFit* locFit, const deque<DCDCTrkHit*>& locStereoHits, double& locTheta, double& locThetaMin, double& locThetaMax, double& locChiSqPerNDF)
3981{
3982 if(locStereoHits.empty())
3983 return false;
3984 /// Find the theta value using the input stereo hits.
3985 /// The values for dPhiStereo and dStereoHitPos.Z() are assumed to be valid.
3986 /// The value of locFit.r0 is also used to calculate theta.
3987 ///
3988 /// This uses a histogramming technique that looks at the overlaps of the
3989 /// angle ranges subtended by each hit between the given target limits.
3990 /// The overlaps usually lead to a range of values for theta. The limits
3991 /// of these are stored in locThetaMin and locThetaMax.
3992 /// The centroid of the range is stored in the theta field.
3993
3994 // We use a simple array to store our histogram here. We don't want to use
3995 // ROOT histograms because they are not thread safe.
3996 unsigned int Nbins = 1000;
3997 unsigned int hist[Nbins];
3998 for(unsigned int i=0; i<Nbins; ++i)
3999 hist[i] = 0; // clear histogram
4000 double bin_width = M_TWO_PI6.28318530717958647692/(double)Nbins;
4001 double hist_low_limit = -M_PI3.14159265358979323846; // lower edge of histogram limits
4002
4003 // Loop over CDC hits, filling the histogram
4004 double r0 = locFit->r0;
4005 for(unsigned int i=0; i < locStereoHits.size(); ++i)
4006 {
4007 DCDCTrkHit *trkhit = locStereoHits[i];
4008
4009 // Calculate upper and lower limits in theta
4010 double alpha = r0*trkhit->dPhiStereo;
4011 if(locFit->h < 0.0)
4012 alpha = -alpha;
4013 double tmin = atan2(alpha, trkhit->dStereoHitPos.Z() - VERTEX_Z_MIN);
4014 double tmax = atan2(alpha, trkhit->dStereoHitPos.Z() - VERTEX_Z_MAX);
4015 if(tmin>tmax)
4016 {
4017 double tmp = tmin;
4018 tmin=tmax;
4019 tmax=tmp;
4020 }
4021 if(DEBUG_LEVEL>3)
4022 cout<<" -- phi_stereo="<<trkhit->dPhiStereo<<" z_stereo="<<trkhit->dStereoHitPos.Z()<<" alpha="<<alpha<<endl;
4023 if(DEBUG_LEVEL>3)
4024 cout<<" -- tmin="<<tmin<<" tmax="<<tmax<<endl;
4025
4026 // Find index of bins corresponding to tmin and tmax
4027 unsigned int imin = (unsigned int)floor((tmin-hist_low_limit)/bin_width);
4028 unsigned int imax = (unsigned int)floor((tmax-hist_low_limit)/bin_width);
4029
4030 // If entire range of this hit is outside of the histogram limit
4031 // then discard this hit.
4032 if(imin>=Nbins)
4033 continue;
4034
4035 // Clip limits of bin range to our histogram limits
4036 if(imin>=Nbins)
4037 imin=Nbins-1;
4038 if(imax>=Nbins)
4039 imax=Nbins-1;
4040
4041 // Increment all bins between imin and imax
4042 for(unsigned int j=imin; j<=imax; ++j)
4043 ++hist[j];
4044 }
4045
4046 // Look for the indexes of the plateau
4047 unsigned int istart=0;
4048 unsigned int iend=0;
4049 for(unsigned int i=1; i<Nbins; ++i)
4050 {
4051 if(hist[i]>hist[istart])
4052 {
4053 istart = i;
4054 if(DEBUG_LEVEL>3)
4055 cout<<" -- istart="<<istart<<" (theta="<<hist_low_limit + bin_width*(0.5+(double)istart)<<" , N="<<hist[i]<<")"<<endl;
4056 }
4057 if(hist[i] == hist[istart])
4058 iend = i;
4059 }
4060
4061 // If there are no entries in the histogram, then return false
4062 if(hist[istart] == 0)
4063 return false;
4064
4065 // Calculate theta limits
4066 locThetaMin = hist_low_limit + bin_width*(0.5+(double)istart);
4067 locThetaMax = hist_low_limit + bin_width*(0.5+(double)iend);
4068 locTheta = (locThetaMax + locThetaMin)/2.0;
4069 if(DEBUG_LEVEL>3)
4070 cout<<"istart="<<istart<<" iend="<<iend<<" theta_min="<<locThetaMin<<" theta_max="<<locThetaMax<<endl;
4071 locChiSqPerNDF = 9.9E5; //NEED TO CALCULATE THIS!!!
4072
4073 return true;
4074}
4075
4076//-------
4077// Find_Z
4078//-------
4079bool DTrackCandidate_factory_CDC::Find_Z(const DHelicalFit* locFit, const deque<DCDCTrkHit*>& locStereoHits, double locThetaMin, double locThetaMax, double& locZ)
4080{
4081 if(locStereoHits.empty())
4082 return false;
4083
4084 /// Find the z value of the vertex using the stereo hits.
4085 /// The values for dPhiStereo and dStereoHitPos.Z() are assumed to be valid.
4086 ///
4087 /// This uses a histogramming technique that looks at the overlaps of the
4088 /// z ranges subtended by each hit between the given theta limits.
4089 /// The overlaps usually lead to a range of values for z_vertex.
4090 /// The centroid of the range is returned as locZ.
4091
4092 // We use a simple array to store our histogram here. We don't want to use
4093 // ROOT histograms because they are not thread safe.
4094 unsigned int Nbins = 300;
4095 unsigned int hist[Nbins];
4096 for(unsigned int i=0; i<Nbins; ++i)
4097 hist[i] = 0; // clear histogram
4098 double bin_width = 0.5; // bins are 5mm
4099 double hist_low_limit = 0.0; // lower edge of histogram limits
4100
4101 // Loop over CDC hits, filling the histogram
4102 double r0 = locFit->r0;
4103 double tan_alpha_min = tan(locThetaMin)/r0;
4104 double tan_alpha_max = tan(locThetaMax)/r0;
4105 for(unsigned int i=0; i< locStereoHits.size(); ++i)
4106 {
4107 DCDCTrkHit* trkhit = locStereoHits[i];
4108
4109 // Calculate upper and lower limits in z
4110 double q_sign = locFit->h > 0.0 ? +1.0:-1.0;
4111 double zmin = trkhit->dStereoHitPos.Z() - q_sign*trkhit->dPhiStereo/tan_alpha_min;
4112 double zmax = trkhit->dStereoHitPos.Z() - q_sign*trkhit->dPhiStereo/tan_alpha_max;
4113 if(zmin>zmax)
4114 {
4115 double tmp = zmin;
4116 zmin=zmax;
4117 zmax=tmp;
4118 }
4119 if(DEBUG_LEVEL>3)
4120 cout<<" -- phi_stereo="<<trkhit->dPhiStereo<<" z_stereo="<<trkhit->dStereoHitPos.Z()<<endl;
4121 if(DEBUG_LEVEL>3)
4122 cout<<" -- zmin="<<zmin<<" zmax="<<zmax<<endl;
4123
4124 // Find index of bins corresponding to tmin and tmax
4125 unsigned int imin = (unsigned int)floor((zmin-hist_low_limit)/bin_width);
4126 unsigned int imax = (unsigned int)floor((zmax-hist_low_limit)/bin_width);
4127
4128 // If entire range of this hit is outside of the histogram limit
4129 // then discard this hit.
4130 if(imax<=0 || imin>=Nbins)
4131 continue;
4132
4133 // Clip limits of bin range to our histogram limits
4134 if(imin>=Nbins)
4135 imin=Nbins-1;
4136 if(imax>=Nbins)
4137 imax=Nbins-1;
4138
4139 // Increment all bins between imin and imax
4140 for(unsigned int j=imin; j<=imax; ++j)
4141 ++hist[j];
4142 }
4143
4144 // Look for the indexes of the plateau
4145 unsigned int istart=0;
4146 unsigned int iend=0;
4147 for(unsigned int i=1; i<Nbins; ++i)
4148 {
4149 if(hist[i]>hist[istart])
4150 {
4151 istart = i;
4152 if(DEBUG_LEVEL>3)
4153 cout<<" -- istart="<<istart<<" (z="<<hist_low_limit + bin_width*(0.5+(double)istart)<<" , N="<<hist[i]<<")"<<endl;
4154 }
4155 if(hist[i] == hist[istart])
4156 iend = i;
4157 }
4158
4159 // If there are no entries in the histogram, then return false
4160 if(hist[istart] == 0)
4161 return false;
4162
4163 // Calculate z limits
4164 double locZMin = hist_low_limit + bin_width*(0.5+(double)istart);
4165 double locZMax = hist_low_limit + bin_width*(0.5+(double)iend);
4166 locZ = (locZMax + locZMin)/2.0;
4167 if(DEBUG_LEVEL>3)
4168 cout<<"istart="<<istart<<" iend="<<iend<<" z_min="<<locZMin<<" z_max="<<locZMax<<" hits[istart]="<<hist[istart]<<endl;
4169 return true;
4170}
4171
4172//---------------------------
4173// Recycle_DCDCSuperLayerSeed
4174//---------------------------
4175void DTrackCandidate_factory_CDC::Recycle_DCDCSuperLayerSeed(DCDCSuperLayerSeed* locCDCSuperLayerSeed)
4176{
4177 // this function should ONLY be called for stereo super layers AFTER the hits have been projected onto the circle (new hit objects were made)
4178 // this is useful for recycling the memory used by the projected hits and seeds
4179 // first loop over the hits: see if can recycle those as well (each hit can be used in multiple seeds)
4180
4181 deque<DCDCTrkHit*> locHits;
4182 locCDCSuperLayerSeed->Get_Hits(locHits);
4183 for(size_t loc_i = 0; loc_i < locHits.size(); ++loc_i)
4184 {
4185 DCDCTrkHit* locCDCTrkHit = locHits[loc_i];
4186 if(dStereoHitNumUsedMap[locCDCTrkHit] == 1) //this is the last remaining DCDCSuperLayerSeed this hit is used in: recycle it
4187 dCDCTrkHitPool_Available.push_back(locCDCTrkHit);
4188 else
4189 --dStereoHitNumUsedMap[locCDCTrkHit];
4190 }
4191 dCDCSuperLayerSeedPool_Available.push_back(locCDCSuperLayerSeed); //recycle
4192}
4193
4194//---------------------------
4195// Recycle_DCDCTrackCircle
4196//---------------------------
4197void DTrackCandidate_factory_CDC::Recycle_DCDCTrackCircle(DCDCTrackCircle* locCDCTrackCircle)
4198{
4199 if(locCDCTrackCircle->fit != NULL__null)
4200 {
4201 dHelicalFitPool_Available.push_back(locCDCTrackCircle->fit);
4202 locCDCTrackCircle->fit = NULL__null;
4203 }
4204 locCDCTrackCircle->Reset();
4205 dCDCTrackCirclePool_Available.push_back(locCDCTrackCircle); //recycle
4206}
4207
4208//----------------------
4209// Set_HitBitPattern_All
4210//----------------------
4211void DTrackCandidate_factory_CDC::Set_HitBitPattern_All(deque<DCDCTrackCircle*>& locCDCTrackCircles)
4212{
4213 unsigned int locNumBits = 8*sizeof(unsigned int);
4214 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
4215 {
4216 DCDCTrackCircle* locCDCTrackCircle = locCDCTrackCircles[loc_i];
4217 locCDCTrackCircle->HitBitPattern.clear();
4218 locCDCTrackCircle->HitBitPattern.resize(dNumCDCHits/(8*sizeof(unsigned int)) + 1);
4219 deque<DCDCTrkHit*> locHits;
4220 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_j)
4221 {
4222 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_j]->Get_Hits(locHits);
4223 for(size_t loc_k = 0; loc_k < locHits.size(); ++loc_k)
4224 locCDCTrackCircle->HitBitPattern[locHits[loc_k]->index/locNumBits] |= 1 << locHits[loc_k]->index % locNumBits;
4225 }
4226
4227 if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
4228 {
4229 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0].size(); ++loc_j)
4230 {
4231 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0][loc_j]->Get_Hits(locHits);
4232 for(size_t loc_k = 0; loc_k < locHits.size(); ++loc_k)
4233 locCDCTrackCircle->HitBitPattern[locHits[loc_k]->index/locNumBits] |= 1 << locHits[loc_k]->index % locNumBits;
4234 }
4235 }
4236 if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
4237 {
4238 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0].size(); ++loc_j)
4239 {
4240 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0][loc_j]->Get_Hits(locHits);
4241 for(size_t loc_k = 0; loc_k < locHits.size(); ++loc_k)
4242 locCDCTrackCircle->HitBitPattern[locHits[loc_k]->index/locNumBits] |= 1 << locHits[loc_k]->index % locNumBits;
4243 }
4244 }
4245 }
4246}
4247
4248//---------------------------
4249// Filter_TrackCircles_Stereo
4250//---------------------------
4251void DTrackCandidate_factory_CDC::Filter_TrackCircles_Stereo(deque<DCDCTrackCircle*>& locCDCTrackCircles)
4252{
4253 if(locCDCTrackCircles.empty())
4254 return;
4255
4256 //sort track circles so that the ones with the best stereo chisq/ndf are first
4257 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByStereoChiSqPerNDFIncreasing);
4258
4259 if(DEBUG_LEVEL > 5)
4260 {
4261 cout << "filter stereo, circles sorted by stereo chisq/ndf" << endl;
4262 Print_TrackCircles(locCDCTrackCircles);
4263 }
4264
4265 //FIRST: Delete super layer seeds if they are shared between circles: delete it from the one with the worst dWeightedChiSqPerDF_Stereo
4266 // This is typically a problem when a track exits the CDC before reaching SL5 or SL6, and picks up the SL5 & SL6 hits from a nearby track instead
4267 // However, DO NOT delete the super layer seed if it is the last one on the track
4268 for(size_t loc_i = 0; loc_i < (locCDCTrackCircles.size() - 1); ++loc_i)
4269 {
4270 //assume this track circle has no wrong seeds (since it has the best chisq/ndf of all circles containing any of these seeds)
4271 DCDCTrackCircle* locTrackCircle_ToCompareTo = locCDCTrackCircles[loc_i];
4272 deque<DCDCSuperLayerSeed*> locStereoSuperLayerSeeds;
4273 locTrackCircle_ToCompareTo->Get_AllStereoSuperLayerSeeds(locStereoSuperLayerSeeds);
4274 //if any of the following track circles has any of the stereo super layer seeds in this track circle, then delete those seeds from those circles
4275 //should recycle...
4276 bool locSeedsStrippedFlag_AnyCircle = false;
4277 for(size_t loc_j = loc_i + 1; loc_j < locCDCTrackCircles.size(); ++loc_j)
4278 {
4279 DCDCTrackCircle* locTrackCircle_Validating = locCDCTrackCircles[loc_j];
4280 if(locTrackCircle_Validating->Get_NumStereoSuperLayerSeeds() <= 1)
4281 continue; //don't strip the last stereo hits!! (stripping isn't perfrect, maybe they are correct, or maybe hit selector will pick the correct ones)
4282 bool locSeedsStrippedFlag = false;
4283 for(size_t loc_k = 0; loc_k < locStereoSuperLayerSeeds.size(); ++loc_k)
4284 {
4285 if(locTrackCircle_Validating->Get_NumStereoSuperLayerSeeds() <= 1)
4286 break;
4287 //remember, can't compare pointers directly (made new objects for projection to track circle), must compare dSuperLayer and dSeedIndex
4288 unsigned int locSuperLayer = locStereoSuperLayerSeeds[loc_k]->dSuperLayer;
4289 unsigned int locSeedIndex = locStereoSuperLayerSeeds[loc_k]->dSeedIndex;
4290 DCDCSuperLayerSeed* locSuperLayerSeed = locTrackCircle_Validating->Get_SuperLayerSeed(locSuperLayer);
4291 if(locSuperLayerSeed == NULL__null)
4292 continue;
4293 if((locSuperLayerSeed->dSuperLayer != locSuperLayer) || (locSuperLayerSeed->dSeedIndex != locSeedIndex))
4294 continue;
4295 //stereo super layer is shared by both track circles, reject it from the one with the worse stereo chisq/ndf (weighted)
4296 if(DEBUG_LEVEL > 10)
4297 cout << "strip SL" << locSuperLayer << " from track circle " << loc_j << endl;
4298 locTrackCircle_Validating->Strip_StereoSuperLayerSeed(locSuperLayer);
4299 locSeedsStrippedFlag = true; //may want to recalc theta/z
4300 locSeedsStrippedFlag_AnyCircle = true;
4301 }
4302 if(locSeedsStrippedFlag) //recalc theta/z to get new chisq/ndf
4303 Select_CDCSuperLayerSeeds(locTrackCircle_Validating, false);
4304 }
4305
4306 if(locSeedsStrippedFlag_AnyCircle) //re-sort if fits have been re-performed
4307 sort(locCDCTrackCircles.begin() + loc_i + 1, locCDCTrackCircles.end(), CDCSortByStereoChiSqPerNDFIncreasing);
4308 }
4309
4310 //restore sort by circle-fit chisq/ndf (weighted)
4311 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByChiSqPerNDFDecreasing);
4312
4313 if(DEBUG_LEVEL > 5)
4314 {
4315 cout << "filter stereo, circles sorted by axial chisq/ndf" << endl;
4316 Print_TrackCircles(locCDCTrackCircles);
4317 }
4318}
4319
4320//---------------
4321// Add_UnusedHits
4322//---------------
4323void DTrackCandidate_factory_CDC::Add_UnusedHits(deque<DCDCTrackCircle*>& locCDCTrackCircles)
4324{
4325 if(DEBUG_LEVEL > 5)
4326 cout << "Add unused hits" << endl;
4327
4328 // If the last super layer of a track is not 7, search for lone, unused hits on the next super layer and add them to the track
4329 // Only add them if they can link to the previous super layer, and wouldn't skip too many rings
4330 // Add at most one hit: prefer the hit on the innermost ring
4331 //If more than one hit on the innermost axial ring: choose the one closest to the circle fit
4332 //If more than one hit on the innermost stereo ring: ambiguous, don't add any hits
4333 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
4334 {
4335 DCDCSuperLayerSeed* locLastSuperLayerSeed = locCDCTrackCircles[loc_i]->Get_LastSuperLayerSeed();
4336 unsigned int locLastSuperLayer = locLastSuperLayerSeed->dSuperLayer;
4337 if(DEBUG_LEVEL > 5)
4338 cout << "i, last super layer = " << loc_i << ", " << locLastSuperLayer << endl;
4339 if(locLastSuperLayer == 7)
4340 continue;
4341 unsigned int locSearchSuperLayer = locLastSuperLayer + 1;
4342 const DHelicalFit* locFit = locCDCTrackCircles[loc_i]->fit;
4343
4344 //make sure the next super layer doesn't correspond to a region where all of the seeds were deleted earlier (density too high)
4345 double locSeedFirstPhi, locSeedLastPhi;
4346 Calc_SuperLayerPhiRange(locLastSuperLayerSeed, locSeedFirstPhi, locSeedLastPhi);
4347 bool locHitDensityTooHighFlag = false;
4348 for(size_t loc_k = 0; loc_k < dRejectedPhiRegions[locSearchSuperLayer].size(); ++loc_k)
4349 {
4350 if(!Check_IfPhiRangesOverlap(locSeedFirstPhi, locSeedLastPhi, dRejectedPhiRegions[locSearchSuperLayer][loc_k].first, dRejectedPhiRegions[locSearchSuperLayer][loc_k].second))
4351 continue;
4352 locHitDensityTooHighFlag = true;
4353 break;
4354 }
4355 if(locHitDensityTooHighFlag)
4356 {
4357 if(DEBUG_LEVEL > 5)
4358 cout << "hit density too high, don't add unused hits" << endl;
4359 continue; //hit density in this region is too high, ignore all hits here
4360 }
4361
4362 //make sure we don't skip too many rings
4363 int locLastHitRing = locLastSuperLayerSeed->dCDCRingSeeds.back().ring;
4364 if((4*locLastSuperLayer - locLastHitRing) > MAX_NUM_RINGSEED_RINGS_SKIPABLE)
4365 {
4366 if(DEBUG_LEVEL > 5)
4367 cout << "too many rings missing at the end of the last super layer: actual, max = " << 4*locLastSuperLayer - locLastHitRing << ", " << MAX_NUM_RINGSEED_RINGS_SKIPABLE << endl;
4368 continue; //too many rings missing at the end of the last super layer
4369 }
4370
4371 wire_direction_t locWireDirection;
4372 if((locSearchSuperLayer == 1) || (locSearchSuperLayer == 4) || (locSearchSuperLayer == 7))
4373 locWireDirection = WIRE_DIRECTION_AXIAL;
4374 else if((locSearchSuperLayer == 2) || (locSearchSuperLayer == 6))
4375 locWireDirection = WIRE_DIRECTION_STEREOLEFT;
4376 else
4377 locWireDirection = WIRE_DIRECTION_STEREORIGHT;
4378
4379 //ok, look for unused hits within a certain angle/distance from the circle fit
4380 DCDCTrkHit* locBestTrkHit = NULL__null;
4381 int locAmbiguousHitRing = -1; //if != -1, ignore all hits in or above this ring //set if > 1 stereo hit that matches on this ring
4382 double locBestDeltaPhi = 9.9E9; //for axial if > 1 hit on innermost ring
4383 for(size_t loc_j = 0; loc_j < cdchits_by_superlayer[locSearchSuperLayer - 1].size(); ++loc_j)
4384 {
4385 DCDCTrkHit* locTrkHit = cdchits_by_superlayer[locSearchSuperLayer - 1][loc_j];
4386 if(locTrkHit->flags & USED)
4387 continue; //not a lone hit: used in a super layer seed
4388 if(locTrkHit->hit->wire->ring == locAmbiguousHitRing)
4389 continue; // already > 1 stereo hit on this ring: ambiguous as to which hit is best
4390
4391 //make sure we don't skip too many rings
4392 int locNumRingsSkipped = locTrkHit->hit->wire->ring - locLastHitRing - 1;
4393 if(locNumRingsSkipped > int(MAX_NUM_RINGSEED_RINGS_SKIPABLE))
4394 {
4395 if(DEBUG_LEVEL > 5)
4396 cout << "would skip too many rings: actual, max = " << locNumRingsSkipped << ", " << MAX_NUM_RINGSEED_RINGS_SKIPABLE << endl;
4397 continue; //would skip too many rings
4398 }
4399
4400 // see if the hit has small-enough transverse distance to the previous super layer
4401 DCDCRingSeed locRingSeed;
4402 locRingSeed.hits.push_back(locTrkHit);
4403 locRingSeed.ring = locTrkHit->hit->wire->ring;
4404 locRingSeed.linked = false;
4405 if(!Attempt_SeedLink(locLastSuperLayerSeed->dCDCRingSeeds.back(), locRingSeed, locLastSuperLayerSeed->dWireOrientation, locWireDirection))
4406 {
4407 if(DEBUG_LEVEL > 5)
4408 cout << "new hit isn't close to wires in previous seed" << endl;
4409 continue; //new hit isn't close to wires in previous seed
4410 }
4411 if(DEBUG_LEVEL > 5)
4412 cout << "hit is close to wires in previous seed, ring = " << locTrkHit->hit->wire->ring << endl;
4413
4414 // If axial, require that the hit be near the circle fit.
4415 double locDeltaPhi = 9.9E9;
4416 if((locSearchSuperLayer == 4) || (locSearchSuperLayer == 7))
4417 {
4418 // Find the position on the circle that is closest to locTrkHit
4419 const DVector3 locOrigin = locTrkHit->hit->wire->origin;
4420 double dx = locOrigin.x() - locFit->x0;
4421 double dy = locOrigin.y() - locFit->y0;
4422 double one_over_denom = 1.0/sqrt(dx*dx + dy*dy);
4423 double x = locFit->x0 + locFit->r0*dx*one_over_denom;
4424 double y = locFit->y0 + locFit->r0*dy*one_over_denom;
4425 DVector2 locCirclePosition(x, y);
4426
4427 // Compare phi values to see if the seeds are close enough to link
4428 locDeltaPhi = fabs(locCirclePosition.Phi() - locOrigin.Phi());
4429 while(locDeltaPhi > M_PI3.14159265358979323846)
4430 locDeltaPhi -= M_TWO_PI6.28318530717958647692;
4431 locDeltaPhi *= 180.0/M_PI3.14159265358979323846;
4432 if(DEBUG_LEVEL > 5)
4433 cout << "hit is axial, check if delta phi is close enough: " << fabs(locDeltaPhi) << ", " << MAX_UNUSED_HIT_LINK_ANGLE << endl;
4434 if(fabs(locDeltaPhi) > MAX_UNUSED_HIT_LINK_ANGLE)
4435 continue; //hit is too far away from the current circle fit
4436 }
4437
4438 //Have a matching unused hit. Now make sure it is the best one so far.
4439
4440 if(locBestTrkHit == NULL__null)
4441 {
4442 //No best hit before, save this result
4443 locBestTrkHit = locTrkHit;
4444 locBestDeltaPhi = locDeltaPhi;
4445 if(DEBUG_LEVEL > 5)
4446 cout << "brand new track hit, delta phi = " << locBestDeltaPhi << endl;
4447 continue;
4448 }
4449
4450 if(locTrkHit->hit->wire->ring > locBestTrkHit->hit->wire->ring)
4451 {
4452 //ring is larger: new hit not as good as the current best one
4453 if(DEBUG_LEVEL > 5)
4454 cout << "new hit not as good as the current best one" << endl;
4455 continue;
4456 }
4457
4458 if(locTrkHit->hit->wire->ring < locBestTrkHit->hit->wire->ring)
4459 {
4460 //ring is smaller: new hit better than the one we had before
4461 locAmbiguousHitRing = -1;
4462 locBestTrkHit = locTrkHit;
4463 locBestDeltaPhi = locDeltaPhi;
4464 if(DEBUG_LEVEL > 5)
4465 cout << "new best track hit (better ring), delta phi = " << locBestDeltaPhi << endl;
4466 continue;
4467 }
4468
4469 //The new hit is on the same ring as the previous best hit.
4470
4471 if((locSearchSuperLayer != 4) && (locSearchSuperLayer != 7))
4472 {
4473 //stereo: can't tell which hit is best, label ring as ambiguous
4474 locAmbiguousHitRing = locBestTrkHit->hit->wire->ring;
4475 locBestTrkHit = NULL__null;
4476 if(DEBUG_LEVEL > 5)
4477 cout << "stereo, can't tell which hit is best, label ring " << locAmbiguousHitRing << " as ambiguous" << endl;
4478 continue;
4479 }
4480
4481 //Axial, see if closest to the track circle (smallest delta phi)
4482 if(locDeltaPhi >= locBestDeltaPhi)
4483 {
4484 //delta-phi is larger: new hit not as good as the current best one
4485 if(DEBUG_LEVEL > 5)
4486 cout << "axial, not the best hit, phis = " << locDeltaPhi << ", " << locBestDeltaPhi << endl;
4487 continue;
4488 }
4489
4490 //delta-phi is smaller: new hit better than the current best one: save it
4491 locBestTrkHit = locTrkHit;
4492 locBestDeltaPhi = locDeltaPhi;
4493 if(DEBUG_LEVEL > 5)
4494 cout << "new best track hit (same ring), delta phi = " << locBestDeltaPhi << endl;
4495 }
4496 if(locBestTrkHit == NULL__null)
4497 continue; // no hit found for this track (or hits were ambiguous)
4498
4499 // add best hit to track: create new DCDCSuperLayerSeed for it, add to circle fit
4500 locBestTrkHit->flags |= USED;
4501 DCDCRingSeed locRingSeed;
4502 locRingSeed.hits.push_back(locBestTrkHit);
4503 locRingSeed.ring = locBestTrkHit->hit->wire->ring;
4504 locRingSeed.linked = true;
4505
4506 DCDCSuperLayerSeed* locNewSuperLayerSeed = Get_Resource_CDCSuperLayerSeed();
4507 locNewSuperLayerSeed->dCDCRingSeeds.push_back(locRingSeed);
4508 locNewSuperLayerSeed->dSuperLayer = locSearchSuperLayer;
4509 locNewSuperLayerSeed->dSeedIndex = dSuperLayerSeeds[locSearchSuperLayer - 1].size();
4510 locNewSuperLayerSeed->linked = true;
4511 locNewSuperLayerSeed->dWireOrientation = locWireDirection;
4512 dSuperLayerSeeds[locSearchSuperLayer - 1].push_back(locNewSuperLayerSeed);
4513 locCDCTrackCircles[loc_i]->Add_LastSuperLayerSeed(locNewSuperLayerSeed);
4514 }
4515}
4516
4517//-----------------------
4518// Create_TrackCandidiate
4519//-----------------------
4520void DTrackCandidate_factory_CDC::Create_TrackCandidiate(DCDCTrackCircle* locCDCTrackCircle)
4521{
4522 DVector3 pos, mom;
4523 if(!Calc_PositionAndMomentum(locCDCTrackCircle, pos, mom))
4524 {
4525 if(DEBUG_LEVEL > 5)
4526 cout << "Track momentum not greater than zero (or NaN), DTrackCandidate object not created." << endl;
4527 return; //don't create object!!
4528 }
4529
4530 DTrackCandidate *locTrackCandidate = new DTrackCandidate;
4531 locTrackCandidate->setCharge(locCDCTrackCircle->fit->h*dFactorForSenseOfRotation);
4532
4533 locTrackCandidate->chisq = locCDCTrackCircle->fit->chisq;
4534 locTrackCandidate->Ndof = locCDCTrackCircle->fit->ndof;
4535 locTrackCandidate->setPosition(pos);
4536 locTrackCandidate->setMomentum(mom);
4537
4538 // Add axial hits (if any)
4539 deque<DCDCTrkHit*> locHits;
4540 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_i)
4541 {
4542 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_i]->Get_Hits(locHits);
4543 for(size_t loc_j = 0; loc_j < locHits.size(); ++loc_j)
4544 {
4545 locTrackCandidate->AddAssociatedObject(locHits[loc_j]->hit);
4546 locTrackCandidate->used_cdc_indexes.push_back(locHits[loc_j]->index);
4547 }
4548 }
4549
4550 // Add inner stereo hits (if any)
4551 if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
4552 {
4553 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0].size(); ++loc_i) //only one seed series: the "best" one
4554 {
4555 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0][loc_i]->Get_Hits(locHits);
4556 for(size_t loc_j = 0; loc_j < locHits.size(); ++loc_j)
4557 {
4558 locTrackCandidate->AddAssociatedObject(locHits[loc_j]->hit);
4559 locTrackCandidate->used_cdc_indexes.push_back(locHits[loc_j]->index);
4560 }
4561 }
4562 }
4563
4564 // Add outer stereo hits (if any)
4565 if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
4566 {
4567 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0].size(); ++loc_i) //only one seed series: the "best" one
4568 {
4569 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0][loc_i]->Get_Hits(locHits);
4570 for(size_t loc_j = 0; loc_j < locHits.size(); ++loc_j)
4571 {
4572 locTrackCandidate->AddAssociatedObject(locHits[loc_j]->hit);
4573 locTrackCandidate->used_cdc_indexes.push_back(locHits[loc_j]->index);
4574 }
4575 }
4576 }
4577
4578 if(DEBUG_LEVEL>3)
4579 cout<<"Final Candidate parameters: p="<<mom.Mag()<<" theta="<<mom.Theta()<<" phi="<<mom.Phi()<<" z="<<pos.Z()<<endl;
4580
4581 _data.push_back(locTrackCandidate);
4582}
4583
4584//-------------------------
4585// Calc_PositionAndMomentum
4586//-------------------------
4587bool DTrackCandidate_factory_CDC::Calc_PositionAndMomentum(DCDCTrackCircle* locCDCTrackCircle, DVector3 &pos, DVector3 &mom)
4588{
4589 // Get the position and momentum at a fixed radius from the beam line
4590
4591 // Direction tangent
4592 double tanl = tan(M_PI_21.57079632679489661923 - locCDCTrackCircle->dTheta);
4593
4594 // Squared radius of cylinder outside start counter but inside CDC inner
4595 // radius
4596 double r2 = 90.0;
4597
4598 // Circle parameters
4599 double xc = locCDCTrackCircle->fit->x0;
4600 double yc = locCDCTrackCircle->fit->y0;
4601 double rc = locCDCTrackCircle->fit->r0;
4602 double rc2 = rc*rc;
4603 double xc2 = xc*xc;
4604 double yc2 = yc*yc;
4605 double xc2_plus_yc2 = xc2 + yc2;
4606
4607 // variables needed for intersection of circles
4608 double a = (r2 - xc2_plus_yc2 - rc2)/(2.*rc);
4609 double temp1 = yc*sqrt(xc2_plus_yc2 - a*a);
4610 double temp2 = xc*a;
4611 double cosphi_plus = (temp2 + temp1)/xc2_plus_yc2;
4612 double cosphi_minus = (temp2 - temp1)/xc2_plus_yc2;
4613
4614 // Check for intersections
4615 if(!isfinite(temp1) || !isfinite(temp2))
4616 {
4617 // We did not find an intersection between the two circles, so return
4618 // sensible defaults for pos and mom
4619 double my_seed_phi = locCDCTrackCircle->fit->phi;
4620 double my_center_phi = atan2(yc,xc);
4621 double xv = xc - rc*cos(my_center_phi);
4622 double yv = yc - rc*sin(my_center_phi);
4623 pos.SetXYZ(xv, yv, locCDCTrackCircle->dVertexZ);
4624
4625 double pt = 0.003*fabs(dMagneticField->GetBz(pos.x(), pos.y(), pos.z()))*rc;
4626 mom.SetXYZ(pt*cos(my_seed_phi), pt*sin(my_seed_phi), pt*tanl);
4627 return (mom.Mag() > 0.0);
4628 }
4629
4630 // if we have intersections, find both solutions
4631 double phi_plus = -acos(cosphi_plus);
4632 double phi_minus = -acos(cosphi_minus);
4633 double x_plus = xc + rc*cosphi_plus;
4634 double x_minus = xc + rc*cosphi_minus;
4635 double y_plus = yc + rc*sin(phi_plus);
4636 double y_minus = yc + rc*sin(phi_minus);
4637
4638 // if the resulting radial position on the circle from the fit does not agree
4639 // with the radius to which we are matching, we have the wrong sign for phi+
4640 // or phi-
4641 double r2_plus = x_plus*x_plus + y_plus*y_plus;
4642 double r2_minus = x_minus*x_minus + y_minus*y_minus;
4643 if(fabs(r2 - r2_plus) > EPS1e-3)
4644 {
4645 phi_plus *= -1.;
4646 y_plus = yc + rc*sin(phi_plus);
4647 }
4648 if(fabs(r2 - r2_minus) > EPS1e-3)
4649 {
4650 phi_minus *= -1.;
4651 y_minus = yc + rc*sin(phi_minus);
4652 }
4653
4654 // Choose phi- or phi+ depending on proximity to one of the cdc hits
4655 DCDCTrkHit* locFirstHit = NULL__null;
4656 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
4657 locFirstHit = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0][0]->dCDCRingSeeds[0].hits[0];
4658 else
4659 locFirstHit = locCDCTrackCircle->dSuperLayerSeeds_Axial[0]->dCDCRingSeeds[0].hits[0];
4660
4661 double xwire = locFirstHit->hit->wire->origin.x();
4662 double ywire = locFirstHit->hit->wire->origin.y();
4663 double dx = x_minus - xwire;
4664 double dy = y_minus - ywire;
4665 double d2_minus = dx*dx + dy*dy;
4666 dx = x_plus - xwire;
4667 dy = y_plus - ywire;
4668 double d2_plus = dx*dx + dy*dy;
4669 if(d2_plus > d2_minus)
4670 {
4671 phi_minus *= -1.;
4672 if(locCDCTrackCircle->fit->h < 0)
4673 phi_minus += M_PI3.14159265358979323846;
4674 double myphi = atan2(yc, xc);
4675 double xv = xc - rc*cos(myphi);
4676 double yv = yc - rc*sin(myphi);
4677 double dx = x_minus - xv;
4678 double dy = y_minus - yv;
4679 double chord = sqrt(dx*dx + dy*dy);
4680 double two_rc = 2.*rc;
4681 double ratio = chord/two_rc;
4682 double ds = (ratio < 1.) ? (two_rc*asin(ratio)) : (two_rc*M_PI_21.57079632679489661923);
4683 pos.SetXYZ(x_minus, y_minus, locCDCTrackCircle->dVertexZ + ds*tanl);
4684
4685 double pt = 0.003*fabs(dMagneticField->GetBz(pos.x(), pos.y(), pos.z()))*rc;
4686 mom.SetXYZ(pt*sin(phi_minus), pt*cos(phi_minus), pt*tanl);
4687 }
4688 else
4689 {
4690 phi_plus *= -1.;
4691 if(locCDCTrackCircle->fit->h < 0)
4692 phi_plus += M_PI3.14159265358979323846;
4693 double myphi = atan2(yc, xc);
4694 double xv = xc - rc*cos(myphi);
4695 double yv = yc - rc*sin(myphi);
4696 double dx = x_plus - xv;
4697 double dy = y_plus - yv;
4698 double chord = sqrt(dx*dx + dy*dy);
4699 double two_rc = 2.*rc;
4700 double ratio = chord/two_rc;
4701 double ds = (ratio < 1.) ? (two_rc*asin(ratio)) : (two_rc*M_PI_21.57079632679489661923);
4702 pos.SetXYZ(x_plus, y_plus, locCDCTrackCircle->dVertexZ + ds*tanl);
4703
4704 double pt =0.003*fabs(dMagneticField->GetBz(pos.x(), pos.y(), pos.z()))*rc;
4705 mom.SetXYZ(pt*sin(phi_plus), pt*cos(phi_plus), pt*tanl);
4706 }
4707 return (mom.Mag() > 0.0);
4708}
4709
4710//------------------
4711// erun
4712//------------------
4713jerror_t DTrackCandidate_factory_CDC::erun(void)
4714{
4715 return NOERROR;
4716}
4717
4718//------------------
4719// fini
4720//------------------
4721jerror_t DTrackCandidate_factory_CDC::fini(void)
4722{
4723 // Delete memory in resource pools
4724 for(size_t loc_i = 0; loc_i < dCDCTrkHitPool_All.size(); ++loc_i)
4725 delete dCDCTrkHitPool_All[loc_i];
4726
4727 for(size_t loc_i = 0; loc_i < dCDCSuperLayerSeedPool_All.size(); ++loc_i)
4728 delete dCDCSuperLayerSeedPool_All[loc_i];
4729
4730 for(size_t loc_i = 0; loc_i < dHelicalFitPool_All.size(); ++loc_i)
4731 delete dHelicalFitPool_All[loc_i];
4732
4733 for(size_t loc_i = 0; loc_i < dCDCTrackCirclePool_All.size(); ++loc_i)
4734 delete dCDCTrackCirclePool_All[loc_i];
4735
4736 return NOERROR;
4737}
4738
4739void DTrackCandidate_factory_CDC::DCDCTrkHit::Reset(void)
4740{
4741 hit = NULL__null;
4742 index = 0;
4743 flags = NONE;
4744 var_z = 0.0;
4745 dStereoHitPos.SetXYZ(0.0, 0.0, 0.0);
4746 dPhiStereo = 0.0;
4747 dValidStereoHitPosFlag = false;
4748}
4749
4750void DTrackCandidate_factory_CDC::DCDCSuperLayerSeed::Reset(void)
4751{
4752 dSuperLayer = 0;
4753 dSeedIndex = 0;
4754 linked = false;
4755 dSpiralLinkParams.clear();
4756 dCDCRingSeeds.clear();
4757}
4758
4759bool DTrackCandidate_factory_CDC::DCDCSuperLayerSeed::Are_AllHitsOnRingShared(const DCDCSuperLayerSeed* locCDCSuperLayerSeed, int locRing) const
4760{
4761 deque<DCDCTrkHit*> locRingHits;
4762 for(size_t loc_i = 0; loc_i < dCDCRingSeeds.size(); ++loc_i)
4763 {
4764 if(dCDCRingSeeds[loc_i].ring != locRing)
4765 continue;
4766 locRingHits = dCDCRingSeeds[loc_i].hits;
4767 break;
4768 }
4769
4770 deque<DCDCTrkHit*> locRingHits_CompareTo;
4771 for(size_t loc_i = 0; loc_i < locCDCSuperLayerSeed->dCDCRingSeeds.size(); ++loc_i)
4772 {
4773 if(locCDCSuperLayerSeed->dCDCRingSeeds[loc_i].ring != locRing)
4774 continue;
4775 locRingHits_CompareTo = locCDCSuperLayerSeed->dCDCRingSeeds[loc_i].hits;
4776 break;
4777 }
4778
4779 return (locRingHits == locRingHits_CompareTo);
4780}
4781
4782void DTrackCandidate_factory_CDC::DCDCTrackCircle::Reset(void)
4783{
4784 dSuperLayerSeeds_Axial.clear();
4785 dSuperLayerSeeds_InnerStereo.clear();
4786 dSuperLayerSeeds_OuterStereo.clear();
4787 fit = NULL__null;
4788 dWeightedChiSqPerDF = 0.0;
4789 dAverageDriftTime = 0.0;
4790 HitBitPattern.clear();
4791 dTheta = 0.0;
4792 dVertexZ = 0.0;
4793 dSpiralTurnRing = -1;
4794 dTruncationSourceCircles.clear();
4795 dHasNonTruncatedSeedsFlag_InnerStereo = false;
4796 dHasNonTruncatedSeedsFlag_OuterStereo = false;
4797 dWeightedChiSqPerDF_Stereo = 0.0;
4798}
4799
4800DTrackCandidate_factory_CDC::DCDCSuperLayerSeed* DTrackCandidate_factory_CDC::DCDCTrackCircle::Get_LastSuperLayerSeed(void) const
4801{
4802 //only checks the first combination of stereo seeds
4803 DCDCSuperLayerSeed* locLastAxialSuperLayerSeed = NULL__null;
1
'locLastAxialSuperLayerSeed' initialized to a null pointer value
4804 if(!dSuperLayerSeeds_Axial.empty())
2
Taking false branch
4805 {
4806 locLastAxialSuperLayerSeed = dSuperLayerSeeds_Axial.back();
4807 if(locLastAxialSuperLayerSeed->dSuperLayer == 7)
4808 return locLastAxialSuperLayerSeed;
4809 }
4810 else if(!dSuperLayerSeeds_OuterStereo.empty())
3
Taking false branch
4811 {
4812 if(dSuperLayerSeeds_OuterStereo[0].back() != NULL__null){
4813 if(dSuperLayerSeeds_OuterStereo[0].back()->dSuperLayer > locLastAxialSuperLayerSeed->dSuperLayer)
4814 return dSuperLayerSeeds_OuterStereo[0].back();
4815 }
4816 }
4817 else if(!dSuperLayerSeeds_InnerStereo.empty())
4
Taking true branch
4818 {
4819 if(dSuperLayerSeeds_InnerStereo[0].back() != NULL__null){
5
Taking true branch
4820 if(dSuperLayerSeeds_InnerStereo[0].back()->dSuperLayer > locLastAxialSuperLayerSeed->dSuperLayer)
6
Access to field 'dSuperLayer' results in a dereference of a null pointer (loaded from variable 'locLastAxialSuperLayerSeed')
4821 return dSuperLayerSeeds_InnerStereo[0].back();
4822 }
4823 }
4824 return locLastAxialSuperLayerSeed;
4825}
4826
4827DTrackCandidate_factory_CDC::DCDCSuperLayerSeed* DTrackCandidate_factory_CDC::DCDCTrackCircle::Get_SuperLayerSeed(unsigned int locSuperLayer) const
4828{
4829 //only checks the first combination of stereo seeds
4830 if((locSuperLayer == 1) || (locSuperLayer == 4) || (locSuperLayer == 7))
4831 {
4832 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_Axial.size(); ++loc_i)
4833 {
4834 if(dSuperLayerSeeds_Axial[loc_i]->dSuperLayer == locSuperLayer)
4835 return dSuperLayerSeeds_Axial[loc_i];
4836 }
4837 return NULL__null;
4838 }
4839 else if((locSuperLayer == 2) || (locSuperLayer == 3))
4840 {
4841 if(dSuperLayerSeeds_InnerStereo.empty())
4842 return NULL__null;
4843 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_InnerStereo[0].size(); ++loc_i)
4844 {
4845 if(dSuperLayerSeeds_InnerStereo[0][loc_i]->dSuperLayer == locSuperLayer)
4846 return dSuperLayerSeeds_InnerStereo[0][loc_i];
4847 }
4848 }
4849 else //outer SL seeds could be listed as inner (e.g. no SL4)
4850 {
4851 if(!dSuperLayerSeeds_OuterStereo.empty())
4852 {
4853 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_OuterStereo[0].size(); ++loc_i)
4854 {
4855 if(dSuperLayerSeeds_OuterStereo[0][loc_i]->dSuperLayer == locSuperLayer)
4856 return dSuperLayerSeeds_OuterStereo[0][loc_i];
4857 }
4858 }
4859 if(!dSuperLayerSeeds_InnerStereo.empty())
4860 {
4861 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_InnerStereo[0].size(); ++loc_i)
4862 {
4863 if(dSuperLayerSeeds_InnerStereo[0][loc_i]->dSuperLayer == locSuperLayer)
4864 return dSuperLayerSeeds_InnerStereo[0][loc_i];
4865 }
4866 }
4867 }
4868 return NULL__null;
4869}
4870
4871void DTrackCandidate_factory_CDC::DCDCTrackCircle::Strip_StereoSuperLayerSeed(unsigned int locSuperLayer)
4872{
4873 //assumes at most one stereo series of each type!!!
4874 deque<DCDCSuperLayerSeed*>::iterator locIterator;
4875 if(!dSuperLayerSeeds_OuterStereo.empty())
4876 {
4877 for(locIterator = dSuperLayerSeeds_OuterStereo[0].begin(); locIterator != dSuperLayerSeeds_OuterStereo[0].end(); ++locIterator)
4878 {
4879 if((*locIterator)->dSuperLayer != locSuperLayer)
4880 continue;
4881 dSuperLayerSeeds_OuterStereo[0].erase(locIterator);
4882 if(dSuperLayerSeeds_OuterStereo[0].empty())
4883 dSuperLayerSeeds_OuterStereo.clear();
4884 return;
4885 }
4886 }
4887 if(!dSuperLayerSeeds_InnerStereo.empty())
4888 {
4889 for(locIterator = dSuperLayerSeeds_InnerStereo[0].begin(); locIterator != dSuperLayerSeeds_InnerStereo[0].end(); ++locIterator)
4890 {
4891 if((*locIterator)->dSuperLayer != locSuperLayer)
4892 continue;
4893 dSuperLayerSeeds_InnerStereo[0].erase(locIterator);
4894 if(dSuperLayerSeeds_InnerStereo[0].empty())
4895 dSuperLayerSeeds_InnerStereo.clear();
4896 return;
4897 }
4898 }
4899}
4900
4901void DTrackCandidate_factory_CDC::DCDCTrackCircle::Add_LastSuperLayerSeed(DCDCSuperLayerSeed* locSuperLayerSeed)
4902{
4903 //assumes at most one stereo series of each type!!!
4904 unsigned int locSuperLayer = locSuperLayerSeed->dSuperLayer;
4905 if((locSuperLayer == 1) || (locSuperLayer == 4) || (locSuperLayer == 7))
4906 dSuperLayerSeeds_Axial.push_back(locSuperLayerSeed);
4907 else if((locSuperLayer == 2) || (locSuperLayer == 3))
4908 {
4909 if(dSuperLayerSeeds_InnerStereo.empty())
4910 dSuperLayerSeeds_InnerStereo.resize(1);
4911 dSuperLayerSeeds_InnerStereo[0].push_back(locSuperLayerSeed);
4912 }
4913 else //is super layer 5 or 6
4914 {
4915 unsigned int locLastAxialLayer = dSuperLayerSeeds_Axial.empty() ? 0 : dSuperLayerSeeds_Axial.back()->dSuperLayer;
4916 if(dSuperLayerSeeds_InnerStereo.empty() || (locLastAxialLayer == 4))
4917 {
4918 if(dSuperLayerSeeds_OuterStereo.empty())
4919 dSuperLayerSeeds_OuterStereo.resize(1);
4920 dSuperLayerSeeds_OuterStereo[0].push_back(locSuperLayerSeed);
4921 }
4922 else //put in inner stereo to keep combinations correct
4923 dSuperLayerSeeds_InnerStereo[0].push_back(locSuperLayerSeed);
4924 }
4925}
4926
4927void DTrackCandidate_factory_CDC::DCDCTrackCircle::Truncate_Circle(unsigned int locNewLastSuperLayer)
4928{
4929 //truncate this circle by rejecting all super layers down to locNewLastSuperLayer
4930 //DOES NOT recycle any memory (these seeds may be used by other circles!!)
4931 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_Axial.size(); ++loc_i)
4932 {
4933 if(dSuperLayerSeeds_Axial[loc_i]->dSuperLayer <= locNewLastSuperLayer)
4934 continue;
4935 ((loc_i == 0) ? dSuperLayerSeeds_Axial.clear() : dSuperLayerSeeds_Axial.resize(loc_i));
4936 break;
4937 }
4938
4939 //outer stereo
4940 deque<deque<DCDCSuperLayerSeed*> >::iterator locIterator, locIterator2;
4941 if(locNewLastSuperLayer < 5)
4942 dSuperLayerSeeds_OuterStereo.clear();
4943 else if(locNewLastSuperLayer < 7)
4944 {
4945 bool locClippedEveryStereoSeedFlag = true;
4946 for(locIterator = dSuperLayerSeeds_OuterStereo.begin(); locIterator != dSuperLayerSeeds_OuterStereo.end();)
4947 {
4948 deque<DCDCSuperLayerSeed*>& locSeedSeries = *locIterator;
4949 bool locClippedstereoSeriesFlag = false;
4950 for(size_t loc_j = 0; loc_j < locSeedSeries.size(); ++loc_j)
4951 {
4952 if(locSeedSeries[loc_j]->dSuperLayer <= locNewLastSuperLayer)
4953 continue;
4954 locClippedstereoSeriesFlag = true;
4955 if(loc_j == 0)
4956 {
4957 locSeedSeries.clear();
4958 break;
4959 }
4960 locSeedSeries.resize(loc_j);
4961 //now, check if another seed series is exactly like this one: if so, clear it
4962 for(locIterator2 = dSuperLayerSeeds_OuterStereo.begin(); locIterator2 != dSuperLayerSeeds_OuterStereo.end(); ++locIterator2)
4963 {
4964 if(locIterator2 == locIterator)
4965 continue;
4966 deque<DCDCSuperLayerSeed*>& locSeedSeries2 = *locIterator2;
4967 if(locSeedSeries == locSeedSeries2)
4968 {
4969 locSeedSeries.clear();
4970 break;
4971 }
4972 }
4973 break;
4974 }
4975 if(!locClippedstereoSeriesFlag)
4976 locClippedEveryStereoSeedFlag = false;
4977 (locSeedSeries.empty() ? (locIterator = dSuperLayerSeeds_OuterStereo.erase(locIterator)) : ++locIterator);
4978 }
4979 if(locClippedEveryStereoSeedFlag)
4980 dHasNonTruncatedSeedsFlag_OuterStereo = false;
4981 }
4982
4983 //inner stereo
4984 if(locNewLastSuperLayer < 2)
4985 {
4986 dSuperLayerSeeds_InnerStereo.clear();
4987 return;
4988 }
4989 else if(locNewLastSuperLayer < 7) //7 instead of 4: could be outer super layers in inner (if SL4 is missing)
4990 {
4991 bool locClippedEveryStereoSeedFlag = true;
4992 for(locIterator = dSuperLayerSeeds_InnerStereo.begin(); locIterator != dSuperLayerSeeds_InnerStereo.end();)
4993 {
4994 deque<DCDCSuperLayerSeed*>& locSeedSeries = *locIterator;
4995 bool locClippedstereoSeriesFlag = false;
4996 for(size_t loc_j = 0; loc_j < locSeedSeries.size(); ++loc_j)
4997 {
4998 if(locSeedSeries[loc_j]->dSuperLayer <= locNewLastSuperLayer)
4999 continue;
5000 locClippedstereoSeriesFlag = true;
5001 if(loc_j == 0)
5002 {
5003 locSeedSeries.clear();
5004 break;
5005 }
5006 locSeedSeries.resize(loc_j);
5007 //now, check if another seed series is exactly like this one: if so, clear it
5008 for(locIterator2 = dSuperLayerSeeds_InnerStereo.begin(); locIterator2 != dSuperLayerSeeds_InnerStereo.end(); ++locIterator2)
5009 {
5010 if(locIterator2 == locIterator)
5011 continue;
5012 deque<DCDCSuperLayerSeed*>& locSeedSeries2 = *locIterator2;
5013 if(locSeedSeries == locSeedSeries2)
5014 {
5015 locSeedSeries.clear();
5016 break;
5017 }
5018 }
5019 break;
5020 }
5021 if(!locClippedstereoSeriesFlag)
5022 locClippedEveryStereoSeedFlag = false;
5023 (locSeedSeries.empty() ? (locIterator = dSuperLayerSeeds_InnerStereo.erase(locIterator)) : ++locIterator);
5024 }
5025 if(locClippedEveryStereoSeedFlag)
5026 dHasNonTruncatedSeedsFlag_InnerStereo = false;
5027 }
5028}
5029
5030void DTrackCandidate_factory_CDC::DCDCTrackCircle::Absorb_TrackCircle(const DCDCTrackCircle* locTrackCircle)
5031{
5032 //used when merging track circles: this track circle will absorb the stereo combinations from the other one
5033 for(size_t loc_i = 0; loc_i < locTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
5034 {
5035 const deque<DCDCSuperLayerSeed*>& locSeedSeries = locTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i];
5036 bool locComboAlreadyPresentFlag = false;
5037 for(size_t loc_j = 0; loc_j < dSuperLayerSeeds_InnerStereo.size(); ++loc_j)
5038 {
5039 if(locSeedSeries == dSuperLayerSeeds_InnerStereo[loc_j])
5040 {
5041 locComboAlreadyPresentFlag = true;
5042 break;
5043 }
5044 else if((locSeedSeries.size() == 1) && (locSeedSeries[0] == dSuperLayerSeeds_InnerStereo[loc_j][0]))
5045 {
5046 locComboAlreadyPresentFlag = true; //is a subset of an existing combo
5047 break;
5048 }
5049 }
5050 if(!locComboAlreadyPresentFlag)
5051 dSuperLayerSeeds_InnerStereo.push_back(locSeedSeries);
5052 }
5053
5054 for(size_t loc_i = 0; loc_i < locTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_i)
5055 {
5056 const deque<DCDCSuperLayerSeed*>& locSeedSeries = locTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i];
5057 bool locComboAlreadyPresentFlag = false;
5058 for(size_t loc_j = 0; loc_j < dSuperLayerSeeds_OuterStereo.size(); ++loc_j)
5059 {
5060 if(locSeedSeries == dSuperLayerSeeds_OuterStereo[loc_j])
5061 {
5062 locComboAlreadyPresentFlag = true;
5063 break;
5064 }
5065 else if((locSeedSeries.size() == 1) && (locSeedSeries[0] == dSuperLayerSeeds_OuterStereo[loc_j][0]))
5066 {
5067 locComboAlreadyPresentFlag = true; //is a subset of an existing combo
5068 break;
5069 }
5070 }
5071 if(!locComboAlreadyPresentFlag)
5072 dSuperLayerSeeds_OuterStereo.push_back(locSeedSeries);
5073 }
5074
5075 if(locTrackCircle->dHasNonTruncatedSeedsFlag_InnerStereo)
5076 dHasNonTruncatedSeedsFlag_InnerStereo = true;
5077 if(locTrackCircle->dHasNonTruncatedSeedsFlag_OuterStereo)
5078 dHasNonTruncatedSeedsFlag_OuterStereo = true;
5079
5080 for(size_t loc_i = 0; loc_i < locTrackCircle->dTruncationSourceCircles.size(); ++loc_i)
5081 {
5082 bool locIsAlreadyTruncationSourceFlag = false;
5083 for(size_t loc_j = 0; loc_j < dTruncationSourceCircles.size(); ++loc_j)
5084 {
5085 if(locTrackCircle->dTruncationSourceCircles[loc_i] != dTruncationSourceCircles[loc_j])
5086 continue;
5087 locIsAlreadyTruncationSourceFlag = true;
5088 break;
5089 }
5090 if(!locIsAlreadyTruncationSourceFlag)
5091 dTruncationSourceCircles.push_back(locTrackCircle->dTruncationSourceCircles[loc_i]);
5092 }
5093}
5094
5095bool DTrackCandidate_factory_CDC::DCDCTrackCircle::Check_IfInputIsSubset(const DCDCTrackCircle* locTrackCircle)
5096{
5097 //returns false if they are effectively identical
5098 if(locTrackCircle->dSuperLayerSeeds_Axial.empty())
5099 return false;
5100 if(locTrackCircle->Get_LastSuperLayerSeed()->dSuperLayer == 7)
5101 return false; //can't be subset if hasn't been truncated yet
5102 if(locTrackCircle->dSuperLayerSeeds_Axial.size() >= dSuperLayerSeeds_Axial.size())
5103 return false; //can't be subset if same # or greater of axial super layers (if identical should merge them instead)
5104
5105 for(size_t loc_i = 0; loc_i < locTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_i)
5106 {
5107 DCDCSuperLayerSeed* locSuperLayerSeed = locTrackCircle->dSuperLayerSeeds_Axial[loc_i];
5108 if(Get_SuperLayerSeed(locSuperLayerSeed->dSuperLayer) != locSuperLayerSeed)
5109 return false;
5110 }
5111 //all axial seeds are a subset, now check the stereo dHasNonTruncatedSeedsFlag flags
5112 DCDCSuperLayerSeed* locLastSuperLayerSeed = locTrackCircle->Get_LastSuperLayerSeed();
5113 if((locLastSuperLayerSeed->dSuperLayer == 1) || (locLastSuperLayerSeed->dSuperLayer == 4))
5114 return true;
5115
5116 DCDCSuperLayerSeed* locLastAxialSuperLayerSeed = locTrackCircle->dSuperLayerSeeds_Axial.back();
5117 if(locLastAxialSuperLayerSeed->dSuperLayer == 4)
5118 return locTrackCircle->dHasNonTruncatedSeedsFlag_OuterStereo;
5119 else
5120 return locTrackCircle->dHasNonTruncatedSeedsFlag_InnerStereo;
5121}
5122
5123void DTrackCandidate_factory_CDC::DCDCTrackCircle::Get_AllStereoSuperLayerSeeds(deque<DCDCSuperLayerSeed*>& locStereoSuperLayerSeeds)
5124{
5125 //assumes there is only one seed series
5126 locStereoSuperLayerSeeds.clear();
5127 if(!dSuperLayerSeeds_InnerStereo.empty())
5128 locStereoSuperLayerSeeds = dSuperLayerSeeds_InnerStereo[0];
5129 if(!dSuperLayerSeeds_OuterStereo.empty())
5130 locStereoSuperLayerSeeds.insert(locStereoSuperLayerSeeds.begin(), dSuperLayerSeeds_OuterStereo[0].begin(), dSuperLayerSeeds_OuterStereo[0].end());
5131}
5132
5133unsigned int DTrackCandidate_factory_CDC::DCDCTrackCircle::Get_NumStereoSuperLayerSeeds(void)
5134{
5135 //assumes there is only one seed series
5136 unsigned int locNumStereoSuperLayerSeeds = 0;
5137 if(!dSuperLayerSeeds_InnerStereo.empty())
5138 locNumStereoSuperLayerSeeds += dSuperLayerSeeds_InnerStereo[0].size();
5139 if(!dSuperLayerSeeds_OuterStereo.empty())
5140 locNumStereoSuperLayerSeeds += dSuperLayerSeeds_OuterStereo[0].size();
5141 return locNumStereoSuperLayerSeeds;
5142}
5143
5144//-------------------------------------------------------------------------
5145// Routines for fitting a line to the stereo data
5146//-------------------------------------------------------------------------
5147// Compute the chi^2 for a line fit given errors in both s and z. Also
5148// computes current best guess for the scaled intercept z0.
5149// Taken from Numerical Recipes in C (2nd ed.), p. 670.
5150double DTrackCandidate_factory_CDC::DCDCLineFit::ChiXY(double lambda)
5151{
5152 double tanl=tan(lambda);
5153 double sumw=0.,avg_s=0.,avg_z=0.,my_chi2=0.;
5154 for (unsigned i=0;i<n;i++){
5155 w[i]=1./(tanl*tanl*var_s[i]+var_z[i]);
5156 sumw+=w[i];
5157 avg_s+=w[i]*s[i];
5158 avg_z+=w[i]*z[i];
5159 }
5160 avg_s/=sumw;
5161 avg_z/=sumw;
5162 z0=avg_z-tanl*avg_s;
5163 for (unsigned int i=0;i<n;i++){
5164 double temp=z[i]-z0-tanl*s[i];
5165 my_chi2+=w[i]*temp*temp;
5166 }
5167 return my_chi2;
5168}
5169
5170// Routine to bracket the minimum chi^2, from Numerical Recipes in C (2nd ed.),
5171// pp. 400-401.
5172#define SHFT(w,x,y,z)(w)=(x);(x)=(y);(y)=(z) (w)=(x);(x)=(y);(y)=(z)
5173#define SIGN(x,y)((y)>=0.0 ? fabs(x):-fabs(x)) ((y)>=0.0 ? fabs(x):-fabs(x))
5174void DTrackCandidate_factory_CDC::DCDCLineFit::BracketMinimumChisq(double &a,double &b,double &c,double &chi2a,double &chi2b,double &chi2c)
5175{
5176 const double GOLD=1.618034;
5177 const double GLIMIT=100.0;
5178
5179 chi2a=ChiXY(a);
5180 chi2b=ChiXY(b);
5181 double chi2u=0.;
5182 if (chi2b>chi2a){
5183 double dummy=0.;
5184 SHFT(dummy,a,b,dummy)(dummy)=(a);(a)=(b);(b)=(dummy);
5185 SHFT(dummy,chi2b,chi2a,dummy)(dummy)=(chi2b);(chi2b)=(chi2a);(chi2a)=(dummy);
5186 }
5187 c=b+GOLD*(b-a);
5188 chi2c=ChiXY(c);
5189 while (chi2b>chi2c){
5190 double r=(b-a)*(chi2b-chi2c);
5191 double q=(b-c)*(chi2b-chi2a);
5192 double q_minus_r=q-r;
5193 double fabs_q_minus_r=fabs(q_minus_r);
5194 double max=(fabs_q_minus_r>1.e-20)?fabs_q_minus_r:1.e-20;
5195 double u=b-((b-c)*q-(b-a)*r)/(2.*SIGN(max,q_minus_r)((q_minus_r)>=0.0 ? fabs(max):-fabs(max)));
5196 double ulim=b+GLIMIT*(c-b);
5197 if ((b-u)*(u-c)>0.0){
5198 chi2u=ChiXY(u);
5199 if (chi2u<chi2c){
5200 a=b;
5201 b=u;
5202 chi2a=chi2b;
5203 chi2b=chi2u;
5204 return;
5205 }
5206 else if (chi2u>chi2b){
5207 c=u;
5208 chi2c=chi2u;
5209 return;
5210 }
5211 u=c+GOLD*(c-b);
5212 chi2u=ChiXY(u);
5213 }
5214 else if ((c-u)*(u-ulim)>0.0){
5215 chi2u=ChiXY(u);
5216 if (chi2u<chi2c){
5217 SHFT(b,c,u,c+GOLD*(c-b))(b)=(c);(c)=(u);(u)=(c+GOLD*(c-b));
5218 SHFT(chi2b,chi2c,chi2u,ChiXY(u))(chi2b)=(chi2c);(chi2c)=(chi2u);(chi2u)=(ChiXY(u));
5219 }
5220 }
5221 else if ((u-ulim)*(ulim-c)>=0.0){
5222 u=ulim;
5223 chi2u=ChiXY(u);
5224 }
5225 else{
5226 u=c+GOLD*(c-b);
5227 chi2u=ChiXY(u);
5228 }
5229 SHFT(a,b,c,u)(a)=(b);(b)=(c);(c)=(u);
5230 SHFT(chi2a,chi2b,chi2c,chi2u)(chi2a)=(chi2b);(chi2b)=(chi2c);(chi2c)=(chi2u);
5231 }
5232}
5233
5234// Use Brent's algorithm to find the "true" (within tolerance) minimum chi^2
5235// after bracketting. Taken from Numerical Recipes in C (2nd. Ed.), pp. 404-405.
5236double DTrackCandidate_factory_CDC::DCDCLineFit::FindMinimumChisq(double ax,double bx, double cx, double &xmin)
5237{
5238 const double CGOLD=0.3819660;
5239 double a=(ax<cx)?ax:cx;
5240 double b=(ax>cx)?ax:cx;
5241 double x=bx,w=bx,v=bx;
5242 double fx=ChiXY(x),fv=fx,fw=fx,fu=0.;
5243 double tol=1e-3,err=0.0,d=0.,u=0.;
5244 for (int iter=1;iter<=100;iter++){
5245 double xm=0.5*(a+b);
5246 double tol1=tol*fabs(x)+1e-10;
5247 double tol2=2.0*tol1;
5248 if (fabs(x-xm)<=(tol2-0.5*(b-a))){
5249 xmin=x;
5250 return fx;
5251 }
5252 if (fabs(err)>tol1){
5253 double r=(x-w)*(fx-fv);
5254 double q=(x-v)*(fx-fw);
5255 double p=(x-v)*q-(x-w)*r;
5256 q=2.0*(q-r);
5257 if (q>0.0) p=-p;
5258 q=fabs(q);
5259 double etemp=err;
5260 err=d;
5261 if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x)|| p>=q*(b-x)){
5262 d=CGOLD*(err=(x>=xm ? a-x : b-x));
5263 }
5264 else{
5265 d=p/q;
5266 u=x+d;
5267 if (u-a < tol2 || b-u < tol2) d=SIGN(tol1,xm-x)((xm-x)>=0.0 ? fabs(tol1):-fabs(tol1));
5268 }
5269 } else {
5270 d=CGOLD*(err=(x>=xm ? a-x : b-x ));
5271 }
5272 u=(fabs(d)>=tol1 ? x+d : x+SIGN(tol1,d)((d)>=0.0 ? fabs(tol1):-fabs(tol1)));
5273 fu=ChiXY(u);
5274 if (fu<=fx){
5275 if (u>=x) a=x;
5276 else b=x;
5277 SHFT(v,w,x,u)(v)=(w);(w)=(x);(x)=(u);
5278 SHFT(fv,fw,fx,fu)(fv)=(fw);(fw)=(fx);(fx)=(fu);
5279 }
5280 else{
5281 if (u<x) a=u;
5282 else b=u;
5283 if (fu<=fw || w==x){
5284 v=w;
5285 w=u;
5286 fv=fw;
5287 fw=fu;
5288 }
5289 else if (fu<=fv || v==x || v==w){
5290 v=u;
5291 fv=fu;
5292 }
5293 }
5294 }
5295 xmin=x;
5296 return fx;
5297}
5298