Bug Summary

File:libraries/TRACKING/DTrackCandidate_factory_CDC.cc
Location:line 2290, column 27
Description:Called C++ object pointer is null

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();)
1
Loop condition is true. Entering loop body
2263 {
2264 DCDCTrackCircle* locCDCTrackCircle = *locIterator;
2265
2266 // get the innermost super layer seed
2267 DCDCSuperLayerSeed* locInnermostSuperLayerSeed = NULL__null;
2
'locInnermostSuperLayerSeed' initialized to a null pointer value
2268 if(!locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
3
Taking false branch
2269 locInnermostSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_Axial.front();
2270 if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
4
Taking false branch
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())
5
Taking false branch
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
2287 //loop over spiral links, see if one of them is a definite spiral link
2288 bool locIsDefinitelyTurningFlag = false;
2289 map<int, DSpiralParams_t>::iterator locSpiralIterator;
2290 for(locSpiralIterator = locInnermostSuperLayerSeed->dSpiralLinkParams.begin(); locSpiralIterator != locInnermostSuperLayerSeed->dSpiralLinkParams.end(); ++locSpiralIterator)
6
Called C++ object pointer is null
2291 {
2292 if(locSpiralIterator->second.dDefiniteSpiralTurnRingFlag == 0)
2293 continue;
2294 locIsDefinitelyTurningFlag = true;
2295 break;
2296 }
2297
2298 //if definitely a spiral turn in its innermost super layer: then delete the track circle: does not originate from the target
2299 if(locIsDefinitelyTurningFlag)
2300 {
2301 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2302 locIterator = locCDCTrackCircles.erase(locIterator);
2303 }
2304 else
2305 ++locIterator;
2306 }
2307}
2308
2309//----------------------
2310// Drop_IncompleteGroups
2311//----------------------
2312void DTrackCandidate_factory_CDC::Drop_IncompleteGroups(deque<DCDCTrackCircle*>& locCDCTrackCircles)
2313{
2314 // Only interested in groups that contain either:
2315 // At least super layer 1 (forward going particles)
2316 // Or at least one stereo layer and one axial layer
2317 deque<DCDCTrackCircle*>::iterator locIterator;
2318 for(locIterator = locCDCTrackCircles.begin(); locIterator != locCDCTrackCircles.end();)
2319 {
2320 DCDCTrackCircle* locCDCTrackCircle = *locIterator;
2321 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
2322 {
2323 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2324 locIterator = locCDCTrackCircles.erase(locIterator); //no axial super layers
2325 continue;
2326 }
2327
2328 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.front()->dSuperLayer == 1)
2329 {
2330 ++locIterator; //has super layer 1: group is OK
2331 continue;
2332 }
2333
2334 if(locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty() && locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
2335 {
2336 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2337 locIterator = locCDCTrackCircles.erase(locIterator); //no stereo super layers
2338 }
2339 else
2340 ++locIterator; //has at least one axial & one stereo super layer: group is OK
2341 }
2342}
2343
2344//------------
2345// Fit_Circles
2346//------------
2347void DTrackCandidate_factory_CDC::Fit_Circles(deque<DCDCTrackCircle*>& locCDCTrackCircles, bool locFitOnlyIfNullFitFlag, bool locAddStereoLayerIntersectionsFlag, bool locFitDuringLinkingFlag)
2348{
2349 /// Do a quick fit of the 2-D projection of the axial hits in the seed to a circle
2350 /// Include intersection between stereo layer seeds if locAddStereoLayerIntersectionsFlag = true (assumes only one stereo seed series for each inner/outer)
2351 /// Determine the sign of the charge (and correspondingly the initial phi angle)
2352 /// assuming that the majority of hits come from the outgoing part of the track.
2353
2354 /// If the resulting circle passes within MAX_HIT_DIST the majority of the hits,
2355 /// then the fit was a success. Otherwise it is a failure and the DCDCTrackCircle is discarded.
2356
2357 /// locFitOnlyIfNullFitFlag should be false unless just truncated the input set of circles
2358 /// if true, this will skip fitting circles that have DCDCTrackCircle::fit != NULL (i.e. were not truncated)
2359
2360 double locAxialStrawVariance = 0.214401; //[d/sqrt(12)]^2, d = 1.604 = straw diameter
2361 deque<DCDCTrackCircle*>::iterator locIterator;
2362 for(locIterator = locCDCTrackCircles.begin(); locIterator != locCDCTrackCircles.end();)
2363 {
2364 DCDCTrackCircle* locCDCTrackCircle = *locIterator;
2365 size_t locNumAxialSuperLayers = locCDCTrackCircle->dSuperLayerSeeds_Axial.size();
2366
2367 if(locFitDuringLinkingFlag && (locNumAxialSuperLayers < 2))
2368 {
2369 //just trying to reduce number of circles during super layer linking; don't try to fit & don't reject yet
2370 ++locIterator;
2371 continue;
2372 }
2373
2374 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
2375 {
2376 //no axial hits: cannot fit circle: reject
2377 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2378 locIterator = locCDCTrackCircles.erase(locIterator);
2379 continue;
2380 }
2381
2382 if(locFitOnlyIfNullFitFlag && (locCDCTrackCircle->fit != NULL__null))
2383 {
2384 ++locIterator;
2385 continue; //fit is not null: & locFitOnlyIfNullFitFlag is true: circle not truncated, don't refit
2386 }
2387
2388 // Setup the fit (add hits)
2389 DHelicalFit* locFit = Get_Resource_HelicalFit();
2390 unsigned int locNumHitsInFit = 0;
2391 for(size_t loc_i = 0; loc_i < locNumAxialSuperLayers; ++loc_i)
2392 {
2393 deque<DCDCTrkHit*> hits;
2394 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_i]->Get_Hits(hits);
2395 for(size_t k = 0; k < hits.size(); ++k)
2396 {
2397 if(hits[k]->flags & OUT_OF_TIME)
2398 continue;
2399 DVector3 pos = hits[k]->hit->wire->origin;
2400 locFit->AddHitXYZ(pos.x(), pos.y(), pos.z(), locAxialStrawVariance, locAxialStrawVariance, 0.0);
2401 ++locNumHitsInFit;
2402 }
2403 }
2404
2405 //add intersections between stereo super layers if desired
2406 //only uses the first combination of stereo super layers (series)
2407 if(locAddStereoLayerIntersectionsFlag)
2408 {
2409 DCDCSuperLayerSeed* locInnerSuperLayerSeed = locCDCTrackCircle->Get_SuperLayerSeed(2);
2410 DCDCSuperLayerSeed* locOuterSuperLayerSeed = locCDCTrackCircle->Get_SuperLayerSeed(3);
2411 if((locInnerSuperLayerSeed != NULL__null) && (locOuterSuperLayerSeed != NULL__null))
2412 {
2413 // Add intersection between super layers 2 & 3
2414 DVector3 locIntersection = Find_IntersectionBetweenSuperLayers(locInnerSuperLayerSeed, locOuterSuperLayerSeed);
2415 //are these the correct uncertainties?
2416 locFit->AddHitXYZ(locIntersection.x(), locIntersection.y(), locIntersection.z(), locAxialStrawVariance, locAxialStrawVariance, 0.0);
2417 }
2418 locInnerSuperLayerSeed = locCDCTrackCircle->Get_SuperLayerSeed(5);
2419 locOuterSuperLayerSeed = locCDCTrackCircle->Get_SuperLayerSeed(6);
2420 if((locInnerSuperLayerSeed != NULL__null) && (locOuterSuperLayerSeed != NULL__null))
2421 {
2422 // Add intersection between super layers 5 & 6
2423 DVector3 locIntersection = Find_IntersectionBetweenSuperLayers(locInnerSuperLayerSeed, locOuterSuperLayerSeed);
2424 //are these the correct uncertainties?
2425 locFit->AddHitXYZ(locIntersection.x(), locIntersection.y(), locIntersection.z(), locAxialStrawVariance, locAxialStrawVariance, 0.0);
2426 }
2427 }
2428
2429 //place a tighter constraint on the beam center if fewer hits: tracks with detached vertices may not go through the center
2430 double locBeamRMS = BeamRMS0.5*locNumAxialSuperLayers; //1sigma = 0.5, 1.0, 1.5 //3sigma = 1.5, 3.0, 4.5
2431
2432 // Perform the fit
2433 if(locFit->FitCircleRiemann(TARGET_Z, locBeamRMS) != NOERROR)
2434 {
2435 if(DEBUG_LEVEL > 3)
2436 cout << "Riemann fit failed. Attempting regression fit..." << endl;
2437 if(locFit->FitCircle() != NOERROR)
2438 {
2439 if(DEBUG_LEVEL > 3)
2440 cout << "Regression circle fit failed. Trying straight line." << endl;
2441 if(locFit->FitCircleStraightTrack() != NOERROR)
2442 {
2443 if(DEBUG_LEVEL > 3)
2444 cout << "Trying straight line fit failed. Giving up." << endl;
2445 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2446 locIterator = locCDCTrackCircles.erase(locIterator);
2447 continue;
2448 }
2449 }
2450 else
2451 locFit->FindSenseOfRotation();
2452 }
2453 else
2454 locFit->GuessChargeFromCircleFit(); // for Riemann fit
2455
2456 // Check if majority of hits are close to circle. Also calculate the avg drift time for the hits close to the circle.
2457 double x0 = locFit->x0;
2458 double y0 = locFit->y0;
2459 double r0 = locFit->r0;
2460 size_t locNumHitsCloseToCircle = 0;
2461 double locAverageDriftTime = 0.0;
2462 unsigned int locTotalNumHits = 0;
2463 for(size_t loc_i = 0; loc_i < locNumAxialSuperLayers; ++loc_i)
2464 {
2465 deque<DCDCTrkHit*> hits;
2466 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_i]->Get_Hits(hits);
2467 locTotalNumHits += hits.size();
2468 for(size_t k = 0; k < hits.size(); ++k)
2469 {
2470 if(hits[k]->flags & OUT_OF_TIME)
2471 continue;
2472 double dx = hits[k]->hit->wire->origin.X() - x0;
2473 double dy = hits[k]->hit->wire->origin.Y() - y0;
2474 double d = sqrt(dx*dx + dy*dy);
2475 if(DEBUG_LEVEL > 15)
2476 cout << "dist = " << d - r0 << endl;
2477 if(fabs(d - r0) > MAX_HIT_DIST)
2478 continue;
2479 ++locNumHitsCloseToCircle;
2480 locAverageDriftTime += hits[k]->hit->tdrift;
2481 }
2482 }
2483 locAverageDriftTime /= ((double)locNumHitsCloseToCircle);
2484
2485 if(DEBUG_LEVEL > 3)
2486 cout << "Circle fit: Nhits=" << locFit->GetNhits() << " h=" << locFit->h << " N=" << locNumHitsCloseToCircle << " phi=" << locFit->phi << endl;
2487 if(locNumHitsCloseToCircle < MIN_SEED_HITS)
2488 {
2489 if(DEBUG_LEVEL > 3)
2490 cout << "Rejected circle fit due to too few hits on track (N=" << locNumHitsCloseToCircle << " MIN_SEED_HITS=" << MIN_SEED_HITS << ")" << endl;
2491 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2492 locIterator = locCDCTrackCircles.erase(locIterator);
2493 continue;
2494 }
2495
2496 if(locNumHitsCloseToCircle < locTotalNumHits/2)
2497 {
2498 if(DEBUG_LEVEL > 3)
2499 cout << "Rejected circle fit due to minority of hits on track (N=" << locNumHitsCloseToCircle << " locTotalNumHits/2=" << locTotalNumHits/2 << ")" << endl;
2500 Recycle_DCDCTrackCircle(locCDCTrackCircle); //recycle
2501 locIterator = locCDCTrackCircles.erase(locIterator);
2502 continue;
2503 }
2504
2505 // Fit is good, save fit results
2506 locCDCTrackCircle->fit = locFit;
2507 double locWeightedChiSqPerDF = ((fabs(locFit->chisq) > 0.0) && (locFit->ndof > 0)) ? locFit->chisq/(float(locFit->ndof*locNumAxialSuperLayers*locNumAxialSuperLayers)) : 9.9E50;
2508 if(DEBUG_LEVEL > 10)
2509 cout << "chisq, ndof, numaxial, weightedchisq = " << locFit->chisq << ", " << locFit->ndof << ", " << locNumAxialSuperLayers << ", " << locWeightedChiSqPerDF << endl;
2510 locCDCTrackCircle->dWeightedChiSqPerDF = locWeightedChiSqPerDF;
2511 locCDCTrackCircle->dAverageDriftTime = locAverageDriftTime;
2512
2513 ++locIterator;
2514 }
2515}
2516
2517//------------------------------------
2518// Find_IntersectionBetweenSuperLayers
2519//------------------------------------
2520DVector3 DTrackCandidate_factory_CDC::Find_IntersectionBetweenSuperLayers(const DCDCSuperLayerSeed* locInnerSuperLayerSeed, const DCDCSuperLayerSeed* locOuterSuperLayerSeed)
2521{
2522 const DCDCRingSeed& locInnerSuperLayerRing = locInnerSuperLayerSeed->dCDCRingSeeds.back(); //last ring of inner super layer
2523 const DCDCRingSeed& locOuterSuperLayerRing = locOuterSuperLayerSeed->dCDCRingSeeds.front(); //first ring of outer super layer
2524
2525 const DCDCWire* first_wire = locInnerSuperLayerRing.hits.front()->hit->wire;
2526 const DCDCWire* second_wire = locOuterSuperLayerRing.hits.front()->hit->wire;
2527
2528 DVector3 u0=first_wire->origin;
2529 DVector3 udir=first_wire->udir;
2530 DVector3 v0=second_wire->origin;
2531 DVector3 vdir=second_wire->udir;
2532 DVector3 diff=u0-v0;
2533 double u_dot_v=udir.Dot(vdir);
2534 double u_dot_diff=udir.Dot(diff);
2535 double v_dot_diff=vdir.Dot(diff);
2536 double scale=1./(1.-u_dot_v*u_dot_v);
2537 double ul=scale*(u_dot_v*v_dot_diff-u_dot_diff);
2538 double vl=scale*(v_dot_diff-u_dot_v*u_dot_diff);
2539 DVector3 pos=0.5*(u0+ul*udir+v0+vl*vdir);
2540
2541 if(DEBUG_LEVEL > 10)
2542 cout << "XYZ intersection between SL" << locInnerSuperLayerSeed->dSuperLayer << " and SL" << locOuterSuperLayerSeed->dSuperLayer << ": " << pos.X() << ", " << pos.Y() << ", " << pos.Z() << endl;
2543 return pos;
2544}
2545
2546/*********************************************************************************************************************************************************************/
2547/*************************************************************** Filter Track Circles and Stereo Wires ***************************************************************/
2548/*********************************************************************************************************************************************************************/
2549
2550//-----------------------
2551// Handle_StereoAndFilter
2552//-----------------------
2553void DTrackCandidate_factory_CDC::Handle_StereoAndFilter(deque<DCDCTrackCircle*>& locCDCTrackCircles, bool locFinalPassFlag)
2554{
2555 // If not on final (refinement) pass: First (potentially) truncate and then filter track circles based on track circle fit results
2556 if(!locFinalPassFlag)
2557 {
2558 Truncate_TrackCircles(locCDCTrackCircles);
2559 Set_HitBitPattern_Axial(locCDCTrackCircles);
2560 Filter_TrackCircles_Axial(locCDCTrackCircles);
2561 if(DEBUG_LEVEL > 5)
2562 {
2563 cout << "post filter clone seeds" << endl;
2564 Print_TrackCircles(locCDCTrackCircles);
2565 }
2566 }
2567
2568 // Create new stereo super layer seeds and select the best ones.
2569 //This is done one track at a time to prevent memory spikes (memory is recycled as "new" stereo hits are rejected)
2570 deque<DCDCTrackCircle*>::iterator locIterator;
2571 size_t locCircleCounter = 0;
2572 for(locIterator = locCDCTrackCircles.begin(); locIterator != locCDCTrackCircles.end();)
2573 {
2574 if(DEBUG_LEVEL > 5)
2575 cout << "Create new Super Layer Seeds for Track Circle " << locCircleCounter << endl;
2576 // Create new super layer seeds: find the intersection between the stereo hits and the circle fit and create new seeds with that information
2577 Create_NewCDCSuperLayerSeeds(*locIterator);
2578 if(DEBUG_LEVEL > 5)
2579 cout << "Select Super Layer Seeds for Track Circle " << locCircleCounter << endl;
2580 // Select the combination of super layer seeds that give the best determination of theta/z for this track.
2581 // Rejects the track if on the final pass and no valid theta/z can be calculated.
2582 if(Select_CDCSuperLayerSeeds(*locIterator, locFinalPassFlag))
2583 ++locIterator;
2584 else
2585 {
2586 Recycle_DCDCTrackCircle(*locIterator); //recycle
2587 locIterator = locCDCTrackCircles.erase(locIterator);
2588 }
2589 ++locCircleCounter;
2590 }
2591 Set_HitBitPattern_All(locCDCTrackCircles);
2592
2593 // If not on final (refinement) pass: Filter track circles based on stereo results
2594 if(!locFinalPassFlag)
2595 {
2596 if(DEBUG_LEVEL > 5)
2597 {
2598 cout << "stereo-selected track circles" << endl;
2599 Print_TrackCircles(locCDCTrackCircles);
2600 }
2601 // Filter out duplicates seeds and definite spiral arms.
2602 Filter_TrackCircles_Stereo(locCDCTrackCircles);
2603 if(DEBUG_LEVEL > 5)
2604 {
2605 cout << "stereo-filtered track circles" << endl;
2606 Print_TrackCircles(locCDCTrackCircles);
2607 }
2608 }
2609}
2610
2611//------------------------
2612// Set_HitBitPattern_Axial
2613//------------------------
2614void DTrackCandidate_factory_CDC::Set_HitBitPattern_Axial(deque<DCDCTrackCircle*>& locCDCTrackCircles)
2615{
2616 unsigned int locNumBits = 8*sizeof(unsigned int);
2617 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
2618 {
2619 DCDCTrackCircle* locCDCTrackCircle = locCDCTrackCircles[loc_i];
2620 locCDCTrackCircle->HitBitPattern.clear();
2621 locCDCTrackCircle->HitBitPattern.resize(dNumCDCHits/(8*sizeof(unsigned int)) + 1);
2622 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_j)
2623 {
2624 deque<DCDCTrkHit*> locHits;
2625 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_j]->Get_Hits(locHits);
2626 for(size_t loc_k = 0; loc_k < locHits.size(); ++loc_k)
2627 locCDCTrackCircle->HitBitPattern[locHits[loc_k]->index/locNumBits] |= 1 << locHits[loc_k]->index % locNumBits;
2628 }
2629 }
2630}
2631
2632//----------------------
2633// Truncate_TrackCircles
2634//----------------------
2635void DTrackCandidate_factory_CDC::Truncate_TrackCircles(deque<DCDCTrackCircle*>& locCDCTrackCircles)
2636{
2637 if(locCDCTrackCircles.empty())
2638 return;
2639
2640 // 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)
2641 // The problem is when these tracks get mixed together, the track that goes most-radially-outward in the CDC generally wins
2642 // e.g. A track not reaching SL7 can match to the other track's SL7, so its fit is worse than it should be
2643 // And, if the two tracks share many hits (such as SL7), then the track not hitting SL7 tends to get rejected
2644
2645 // It should almost be impossible for two tracks to have identical DCDCSuperLayerSeed's AND for all hits to belong to both tracks.
2646 // Two crossing tracks should almost always have different DCDCSuperLayerSeed's that share hits between them.
2647 // If the DCDCSuperLayerSeed truly ought to belong to both tracks, stripping hits won't kill the track anyway: it should still be reconstructable
2648
2649 // To save these tracks, look for pairs of tracks that have identical axial DCDCSuperLayerSeed's: first in super layer 7
2650 // If the seeds in SL7 are identical, strip SL6 & SL7 from the track with the worse circle-fit weighted chisq/ndf.
2651 // 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.
2652 // If the axial super layer seeds in the truncated circle are not unique, merge it with the other existing DCDCTrackCircle
2653 // If this truncated DCDCTrackCircle is merely a subset of a different DCDCTrackCircle, delete it.
2654 // Refit the newly-truncated track circles.
2655
2656 // Next look for pairs of tracks that have identical DCDCSuperLayerSeed's in super layer 4
2657 // 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))
2658 // Otherwise, if the seeds in SL4 are identical, strip SL3+ from the track with the worse circle-fit weighted chisq/ndf and refit it.
2659 // If the axial super layer seeds in the truncated circle are not unique, merge it with the other existing DCDCTrackCircle
2660 // If this truncated DCDCTrackCircle is merely a subset of a different DCDCTrackCircle, delete it.
2661 // Refit the newly-truncated track circles.
2662
2663 //first initialize "DCDCTrackCircle::dHasNonTruncatedSeedsFlag" variables
2664 //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
2665 //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.
2666 //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
2667 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
2668 {
2669 if(!locCDCTrackCircles[loc_i]->dSuperLayerSeeds_InnerStereo.empty())
2670 locCDCTrackCircles[loc_i]->dHasNonTruncatedSeedsFlag_InnerStereo = true;
2671 if(!locCDCTrackCircles[loc_i]->dSuperLayerSeeds_OuterStereo.empty())
2672 locCDCTrackCircles[loc_i]->dHasNonTruncatedSeedsFlag_OuterStereo = true;
2673 else if(locCDCTrackCircles[loc_i]->Get_LastSuperLayerSeed()->dSuperLayer > 4)
2674 locCDCTrackCircles[loc_i]->dHasNonTruncatedSeedsFlag_OuterStereo = true; //e.g. SL4 is missing, so outers are grouped with inners
2675 }
2676
2677 //assumes input circles are sorted, with largest chisq/ndf first and smallest last
2678 //want to compare the worst fit to the best fit
2679 deque<DCDCTrackCircle*>::iterator locIterator_Validating, locIterator_ToCompareTo;
2680
2681 // FIRST CHECK FOR SAME SUPER LAYER SEED IN SL7
2682 bool locTruncationPerformedFlag = false;
2683 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end(); ++locIterator_Validating)
2684 {
2685 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating; //this has the worst circle-fit weighted chisq/ndf (and decreasing)
2686 if(DEBUG_LEVEL > 10)
2687 {
2688 cout << "validating: search for SL7 truncation for circle with axial seeds:" << endl;
2689 for(size_t loc_j = 0; loc_j < locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.size(); ++loc_j)
2690 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2691 }
2692
2693 DCDCSuperLayerSeed* locSuperLayerSeed_Validating = locCDCTrackCircle_Validating->Get_SuperLayerSeed(7);
2694 if(locSuperLayerSeed_Validating == NULL__null)
2695 continue; //this track circle has no SL7
2696
2697 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
2698 {
2699 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo; //this has the best circle-fit weighted chisq/ndf (and increasing)
2700 if(DEBUG_LEVEL > 10)
2701 {
2702 cout << "to-compare-to: search for SL7 truncation for circle with axial seeds:" << endl;
2703 for(size_t loc_j = 0; loc_j < locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial.size(); ++loc_j)
2704 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2705 }
2706
2707 DCDCSuperLayerSeed* locSuperLayerSeed_ToCompareTo = locCDCTrackCircle_ToCompareTo->Get_SuperLayerSeed(7);
2708 if(locSuperLayerSeed_Validating != locSuperLayerSeed_ToCompareTo)
2709 continue; //different seed for SL7
2710
2711 //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
2712 // if two tracks are crossing they should almost always have different super layer seeds (that share hits)
2713 // 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
2714
2715 //check to see if SL4 is identical also
2716 locSuperLayerSeed_Validating = locCDCTrackCircle_Validating->Get_SuperLayerSeed(4);
2717 locSuperLayerSeed_ToCompareTo = locCDCTrackCircle_ToCompareTo->Get_SuperLayerSeed(4);
2718 if(locSuperLayerSeed_Validating == locSuperLayerSeed_ToCompareTo)
2719 {
2720 // SL4 is identical (or missing from both): strip everything from (and including) SL3 and outwards from the track with lower chisq/ndf
2721 //don't trust SL3 since it led to SL4: hit selector can (in theory) pick up the hits later if needed
2722 //impossible for SL1 to also be identical: would be same object because all axials would be the same
2723 if(DEBUG_LEVEL > 5)
2724 cout << "SL7's and SL4's identical: truncate to SL2" << endl;
2725 locCDCTrackCircle_Validating->Truncate_Circle(2); //2: new last super layer
2726 if(DEBUG_LEVEL > 20)
2727 {
2728 cout << "post truncate" << endl;
2729 Print_TrackCircle(locCDCTrackCircle_Validating);
2730 }
2731 }
2732 else
2733 {
2734 // SL4 is different: strip SL6 & SL7 from the track with lower chisq/ndf
2735 //don't trust SL6 since it led to SL7: hit selector can (in theory) pick up the hits later if needed
2736 if(DEBUG_LEVEL > 5)
2737 cout << "SL7's identical (but not SL4's): truncate to SL5" << endl;
2738 locCDCTrackCircle_Validating->Truncate_Circle(5); //5: new last super layer
2739 if(DEBUG_LEVEL > 20)
2740 {
2741 cout << "post truncate" << endl;
2742 Print_TrackCircle(locCDCTrackCircle_Validating);
2743 }
2744 }
2745
2746 //reset fit
2747 dHelicalFitPool_Available.push_back(locCDCTrackCircle_Validating->fit); //will redo the fit: recycle the memory
2748 locCDCTrackCircle_Validating->fit = NULL__null; //indicate need to reperform fit
2749
2750 //update truncation sources
2751 locCDCTrackCircle_Validating->dTruncationSourceCircles.push_back(locCDCTrackCircle_ToCompareTo);
2752
2753 locTruncationPerformedFlag = true;
2754 break; //truncation successful
2755 }
2756 }
2757
2758 if(locTruncationPerformedFlag)
2759 {
2760 //now merge any track circles that have identical axial super layers
2761 //e.g. two tracks have SL1 & SL4 but different SL7, and their SL7's are rejected by other tracks who have the same SL7s
2762 //loop order doesn't really matter here, keeping consistent anyway
2763 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2764 {
2765 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2766 bool locMergedTrackCircleFlag = false;
2767 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
2768 {
2769 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2770 if(locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial != locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial)
2771 continue; //not identical
2772 //identical axial super layers: merge track circles (absorb the "Validating" one into the "ToCompareTo" one //which is which doesn't matter)
2773 if(DEBUG_LEVEL > 20)
2774 {
2775 cout << "sl7 merging circles: validating = " << endl;
2776 Print_TrackCircle(locCDCTrackCircle_Validating);
2777 cout << "sl7 merging circles: to-compare-to = " << endl;
2778 Print_TrackCircle(locCDCTrackCircle_ToCompareTo);
2779 }
2780 locCDCTrackCircle_ToCompareTo->Absorb_TrackCircle(locCDCTrackCircle_Validating);
2781 if(DEBUG_LEVEL > 20)
2782 {
2783 cout << "sl7 merge circles: output = " << endl;
2784 Print_TrackCircle(locCDCTrackCircle_ToCompareTo);
2785 }
2786 locMergedTrackCircleFlag = true;
2787 break;
2788 }
2789 if(locMergedTrackCircleFlag)
2790 {
2791 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
2792 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
2793 }
2794 else
2795 ++locIterator_Validating;
2796 }
2797
2798 //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)
2799 //is a subset if the axials are a subset AND the outermost stereo layers dHasNonTruncatedSeedsFlag is false
2800 //if one is a subset of another, delete it
2801 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2802 {
2803 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2804 if(locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.size() == 3)
2805 {
2806 ++locIterator_Validating;
2807 continue; //not going to be a subset
2808 }
2809 if(DEBUG_LEVEL > 20)
2810 {
2811 cout << "sl7 checking-for-subsets: validating = " << endl;
2812 Print_TrackCircle(locCDCTrackCircle_Validating);
2813 }
2814 bool locRejectTrackFlag = false;
2815 for(locIterator_ToCompareTo = locCDCTrackCircles.begin(); locIterator_ToCompareTo != locCDCTrackCircles.end(); ++locIterator_ToCompareTo)
2816 {
2817 if(locIterator_ToCompareTo == locIterator_Validating)
2818 continue;
2819 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2820 if(DEBUG_LEVEL > 20)
2821 {
2822 cout << "sl7 checking-for-subsets: to-compare-to = " << endl;
2823 Print_TrackCircle(locCDCTrackCircle_ToCompareTo);
2824 }
2825
2826 if(!locCDCTrackCircle_ToCompareTo->Check_IfInputIsSubset(locCDCTrackCircle_Validating))
2827 continue; //not a subset
2828
2829 if(DEBUG_LEVEL > 10)
2830 cout << "rejecting subset circle" << endl;
2831 locRejectTrackFlag = true; //is a subset
2832 break;
2833 }
2834 if(locRejectTrackFlag)
2835 {
2836 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
2837 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
2838 }
2839 else
2840 ++locIterator_Validating;
2841 }
2842
2843 //now fit the newly-truncated track circles
2844 Fit_Circles(locCDCTrackCircles, true, false); //true: fit only truncated circles //false: don't add stereo intersections
2845 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByChiSqPerNDFDecreasing); //sort by fit chisq/ndf
2846 if(DEBUG_LEVEL > 5)
2847 {
2848 cout << "Post-SL7-turncation track circles" << endl;
2849 Print_TrackCircles(locCDCTrackCircles);
2850 }
2851 }
2852
2853 // NOW CHECK FOR SAME SUPER LAYER SEED IN SL4
2854 locTruncationPerformedFlag = false;
2855 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2856 {
2857 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2858 if(DEBUG_LEVEL > 10)
2859 {
2860 cout << "validating: search for SL4 truncation for circle with axial seeds:" << endl;
2861 for(size_t loc_j = 0; loc_j < locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.size(); ++loc_j)
2862 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2863 }
2864
2865 DCDCSuperLayerSeed* locSuperLayerSeed_Validating = locCDCTrackCircle_Validating->Get_SuperLayerSeed(4);
2866 if(locSuperLayerSeed_Validating == NULL__null)
2867 {
2868 ++locIterator_Validating;
2869 continue; //this track circle has no SL4
2870 }
2871
2872 if(locCDCTrackCircle_Validating->Get_SuperLayerSeed(7) != NULL__null)
2873 {
2874 //this track circle has a unique SL7 (if not unique would have been truncated earlier): do not truncate it
2875 //rejecting SL4 from the track with the SL7 would leave an unphysical combination
2876 //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
2877 //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)
2878 ++locIterator_Validating;
2879 continue;
2880 }
2881
2882 DCDCSuperLayerSeed* locSuperLayerSeed1_Validating = locCDCTrackCircle_Validating->Get_SuperLayerSeed(1);
2883 bool locRejectTrackFlag = false;
2884 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
2885 {
2886 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2887 if(DEBUG_LEVEL > 10)
2888 {
2889 cout << "to-compare-to: search for SL4 truncation for circle with axial seeds:" << endl;
2890 for(size_t loc_j = 0; loc_j < locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial.size(); ++loc_j)
2891 cout << "Axial Super Layer, Seed Index = " << locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial[loc_j]->dSuperLayer << ", " << locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial[loc_j]->dSeedIndex << endl;
2892 }
2893
2894 DCDCSuperLayerSeed* locSuperLayerSeed_ToCompareTo = locCDCTrackCircle_ToCompareTo->Get_SuperLayerSeed(4);
2895 if(locSuperLayerSeed_Validating != locSuperLayerSeed_ToCompareTo)
2896 continue; //different seed for SL4
2897
2898 //SL4 is identical, check status of SL1
2899 DCDCSuperLayerSeed* locSuperLayerSeed1_ToCompareTo = locCDCTrackCircle_ToCompareTo->Get_SuperLayerSeed(1);
2900 if(locSuperLayerSeed1_Validating == locSuperLayerSeed1_ToCompareTo)
2901 {
2902 //SL1 & SL4 are identical: only difference is that locCDCTrackCircle_ToCompareTo has SL7
2903 //locCDCTrackCircle_Validating is merely a subset of locCDCTrackCircle_ToCompareTo (which has a better chisq/ndf): reject it
2904 if(DEBUG_LEVEL > 5)
2905 cout << "SL1 and SL4 are identical, while SL7 of validating is missing: reject validating track" << endl;
2906 locRejectTrackFlag = true;
2907 break;
2908 }
2909
2910 //track circles have identical seeds in SL4, and at least one track does not have an SL7 (although both may not):
2911 //should almost never be possible for both to be good tracks AND for all of the hits to belong to both
2912 // if two tracks are crossing they should almost always have different super layer seeds (that share hits)
2913 // 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
2914
2915 //truncate the circle //don't trust SL3 since it led to SL4: hit selector can (in theory) pick up the hits later if needed
2916 if(DEBUG_LEVEL > 5)
2917 cout << "SL4 is identical, SL1 is not, while SL7 of validating is missing: truncate to SL2" << endl;
2918 locCDCTrackCircle_Validating->Truncate_Circle(2); //2: new last super layer
2919
2920 //reset fit if not already done
2921 if(locCDCTrackCircle_Validating->fit != NULL__null)
2922 {
2923 dHelicalFitPool_Available.push_back(locCDCTrackCircle_Validating->fit); //will redo the fit: recycle the memory
2924 locCDCTrackCircle_Validating->fit = NULL__null; //indicate need to reperform fit
2925 }
2926
2927 //update truncation sources
2928 bool locIsAlreadyTruncationSourceFlag = false;
2929 for(size_t loc_i = 0; loc_i < locCDCTrackCircle_Validating->dTruncationSourceCircles.size(); ++loc_i)
2930 {
2931 if(locCDCTrackCircle_Validating->dTruncationSourceCircles[loc_i] != locCDCTrackCircle_ToCompareTo)
2932 continue;
2933 locIsAlreadyTruncationSourceFlag = true;
2934 break;
2935 }
2936 if(!locIsAlreadyTruncationSourceFlag)
2937 locCDCTrackCircle_Validating->dTruncationSourceCircles.push_back(locCDCTrackCircle_ToCompareTo);
2938
2939 locTruncationPerformedFlag = true;
2940 break; //truncation successful
2941 }
2942
2943 if(locRejectTrackFlag)
2944 {
2945 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
2946 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
2947 }
2948 else
2949 ++locIterator_Validating;
2950 }
2951
2952 if(locTruncationPerformedFlag)
2953 {
2954 //now merge any track circles that have identical axial super layers
2955 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2956 {
2957 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2958 bool locMergedTrackCircleFlag = false;
2959 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
2960 {
2961 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2962 if(locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial != locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial)
2963 continue; //not identical
2964 //identical axial super layers: merge track circles (absorb the "Validating" one into the "ToCompareTo" one //which is which doesn't matter)
2965 locCDCTrackCircle_ToCompareTo->Absorb_TrackCircle(locCDCTrackCircle_Validating);
2966 locMergedTrackCircleFlag = true;
2967 break;
2968 }
2969 if(locMergedTrackCircleFlag)
2970 {
2971 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
2972 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
2973 }
2974 else
2975 ++locIterator_Validating;
2976 }
2977
2978 //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)
2979 //is a subset if the axials are a subset AND the outermost stereo layers dHasNonTruncatedSeedsFlag is false
2980 //if one is a subset of another, delete it
2981 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
2982 {
2983 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
2984 bool locRejectTrackFlag = false;
2985 if(DEBUG_LEVEL > 20)
2986 {
2987 cout << "sl4 checking-for-subsets: validating = " << endl;
2988 Print_TrackCircle(locCDCTrackCircle_Validating);
2989 }
2990 for(locIterator_ToCompareTo = locCDCTrackCircles.begin(); locIterator_ToCompareTo != locCDCTrackCircles.end(); ++locIterator_ToCompareTo)
2991 {
2992 if(locIterator_ToCompareTo == locIterator_Validating)
2993 continue;
2994 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
2995 if(DEBUG_LEVEL > 20)
2996 {
2997 cout << "sl4 checking-for-subsets: to-compare-to = " << endl;
2998 Print_TrackCircle(locCDCTrackCircle_ToCompareTo);
2999 }
3000
3001 if(!locCDCTrackCircle_ToCompareTo->Check_IfInputIsSubset(locCDCTrackCircle_Validating))
3002 continue; //not a subset
3003
3004 locRejectTrackFlag = true; //is a subset
3005 if(DEBUG_LEVEL > 10)
3006 cout << "rejecting subset circle" << endl;
3007 break;
3008 }
3009 if(locRejectTrackFlag)
3010 {
3011 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
3012 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
3013 }
3014 else
3015 ++locIterator_Validating;
3016 }
3017
3018 //now fit the newly-truncated track circles
3019 Fit_Circles(locCDCTrackCircles, true, false); //true: fit only truncated circles //false: don't add stereo intersections
3020 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByChiSqPerNDFDecreasing); //sort by fit chisq/ndf
3021 if(DEBUG_LEVEL > 5)
3022 {
3023 cout << "Post-SL4-turncation track circles" << endl;
3024 Print_TrackCircles(locCDCTrackCircles);
3025 }
3026 }
3027}
3028
3029//--------------------------
3030// Filter_TrackCircles_Axial
3031//--------------------------
3032void DTrackCandidate_factory_CDC::Filter_TrackCircles_Axial(deque<DCDCTrackCircle*>& locCDCTrackCircles)
3033{
3034 if(locCDCTrackCircles.empty())
3035 return;
3036
3037 //assumes input circles are sorted, with largest chisq/ndf first and smallest last
3038 //want to compare the worst fit to the best fit
3039 deque<DCDCTrackCircle*>::iterator locIterator_Validating, locIterator_ToCompareTo;
3040
3041 //FIRST: If circles share > MAX_COMMON_HIT_FRACTION of axial hits, reject circle with larger chisq/ndf
3042 for(locIterator_Validating = locCDCTrackCircles.begin(); locIterator_Validating != locCDCTrackCircles.end();)
3043 {
3044 DCDCTrackCircle* locCDCTrackCircle_Validating = *locIterator_Validating;
3045 if(locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.empty())
3046 continue; //no axial hits to share (somehow)
3047
3048 size_t locNumHits_Validating = 0;
3049 deque<DCDCTrkHit*> hits;
3050 for(size_t loc_i = 0; loc_i < locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial.size(); ++loc_i)
3051 {
3052 locCDCTrackCircle_Validating->dSuperLayerSeeds_Axial[loc_i]->Get_Hits(hits);
3053 locNumHits_Validating += hits.size();
3054 }
3055
3056 bool locRejectTrackCircleFlag = false;
3057 for(locIterator_ToCompareTo = --(locCDCTrackCircles.end()); locIterator_ToCompareTo != locIterator_Validating; --locIterator_ToCompareTo)
3058 {
3059 DCDCTrackCircle* locCDCTrackCircle_ToCompareTo = *locIterator_ToCompareTo;
3060 if(locCDCTrackCircle_ToCompareTo->dSuperLayerSeeds_Axial.empty())
3061 continue; //no axial hits to share (somehow)
3062
3063 //If seeds share > MAX_COMMON_HIT_FRACTION of hits, reject seed with larger chisq/ndf
3064 size_t locNumCommonHits = 0;
3065 size_t locNumWords = locCDCTrackCircle_Validating->HitBitPattern.size();
3066 for(size_t loc_i = 0; loc_i < locNumWords; ++loc_i)
3067 locNumCommonHits += bitcount(locCDCTrackCircle_Validating->HitBitPattern[loc_i] & locCDCTrackCircle_ToCompareTo->HitBitPattern[loc_i]);
3068 double locHitFraction = double(locNumCommonHits)/double(locNumHits_Validating);
3069
3070 if(locHitFraction > MAX_COMMON_HIT_FRACTION)
3071 {
3072 locRejectTrackCircleFlag = true;
3073 break;
3074 }
3075 }
3076 if(locRejectTrackCircleFlag)
3077 {
3078 //free up some memory by clearing the seed deques via reset
3079 Recycle_DCDCTrackCircle(locCDCTrackCircle_Validating); //recycle
3080 locIterator_Validating = locCDCTrackCircles.erase(locIterator_Validating);
3081 }
3082 else
3083 ++locIterator_Validating; //track circle is valid (for now)
3084 }
3085}
3086
3087//-----------------------------
3088// Create_NewCDCSuperLayerSeeds
3089//-----------------------------
3090void DTrackCandidate_factory_CDC::Create_NewCDCSuperLayerSeeds(DCDCTrackCircle* locCDCTrackCircle)
3091{
3092 // Create new stereo DCDCSuperLayerSeed objects, finding the intersections of each stereo wire with the fit circle
3093
3094 map<DCDCSuperLayerSeed*, DCDCSuperLayerSeed*> locConvertedSuperLayerSeeds;
3095 map<DCDCSuperLayerSeed*, DCDCSuperLayerSeed*>::iterator locMapIterator; //map from orig super layer to new super layer
3096 map<DCDCTrkHit*, DCDCTrkHit*> locProjectedStereoHitMap; //map from orig (super layer, non-circle-projected) stereo hit to circle-projected (hit-z-group) hit
3097
3098 //inner stereo
3099 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
3100 {
3101 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i].size(); ++loc_j)
3102 {
3103 DCDCSuperLayerSeed* locCDCSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_j];
3104 locMapIterator = locConvertedSuperLayerSeeds.find(locCDCSuperLayerSeed);
3105 if(locMapIterator != locConvertedSuperLayerSeeds.end())
3106 {
3107 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_j] = locMapIterator->second;
3108 continue; //already converted
3109 }
3110 DCDCSuperLayerSeed* locNewCDCSuperLayerSeed = Create_NewStereoSuperLayerSeed(locCDCSuperLayerSeed, locCDCTrackCircle, locProjectedStereoHitMap);
3111 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_j] = locNewCDCSuperLayerSeed;
3112 locConvertedSuperLayerSeeds[locCDCSuperLayerSeed] = locNewCDCSuperLayerSeed;
3113 }
3114 }
3115
3116 //outer stereo
3117 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_i)
3118 {
3119 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i].size(); ++loc_j)
3120 {
3121 DCDCSuperLayerSeed* locCDCSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i][loc_j];
3122 locMapIterator = locConvertedSuperLayerSeeds.find(locCDCSuperLayerSeed);
3123 if(locMapIterator != locConvertedSuperLayerSeeds.end())
3124 {
3125 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i][loc_j] = locMapIterator->second;
3126 continue; //already converted
3127 }
3128 DCDCSuperLayerSeed* locNewCDCSuperLayerSeed = Create_NewStereoSuperLayerSeed(locCDCSuperLayerSeed, locCDCTrackCircle, locProjectedStereoHitMap);
3129 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i][loc_j] = locNewCDCSuperLayerSeed;
3130 locConvertedSuperLayerSeeds[locCDCSuperLayerSeed] = locNewCDCSuperLayerSeed;
3131 }
3132 }
3133}
3134
3135//-------------------------------
3136// Create_NewStereoSuperLayerSeed
3137//-------------------------------
3138DTrackCandidate_factory_CDC::DCDCSuperLayerSeed* DTrackCandidate_factory_CDC::Create_NewStereoSuperLayerSeed(DCDCSuperLayerSeed* locCDCSuperLayerSeed, const DCDCTrackCircle* locCDCTrackCircle, map<DCDCTrkHit*, DCDCTrkHit*>& locProjectedStereoHitMap)
3139{
3140 //locProjectedStereoHitMap is map from orig (super layer, non-circle-projected) stereo hit to circle-projected hit
3141 DCDCSuperLayerSeed* locNewCDCSuperLayerSeed = Get_Resource_CDCSuperLayerSeed();
3142 *locNewCDCSuperLayerSeed = *locCDCSuperLayerSeed;
3143
3144 // Project all stereo hits in this super layer onto the circle fit
3145
3146 for(size_t loc_i = 0; loc_i < locCDCSuperLayerSeed->dCDCRingSeeds.size(); ++loc_i)
3147 {
3148 deque<DCDCTrkHit*>& hits = locCDCSuperLayerSeed->dCDCRingSeeds[loc_i].hits;
3149 deque<DCDCTrkHit*> locProjectedHits;
3150 for(size_t loc_l = 0; loc_l < hits.size(); ++loc_l)
3151 {
3152 if(fabs(hits[loc_l]->hit->tdrift - locCDCTrackCircle->dAverageDriftTime) > MAX_SEED_TIME_DIFF)
3153 continue; // Ignore hits that are out of time with the group
3154
3155 // If haven't done so already, Calculate intersection points between circle and stereo wire
3156 DCDCTrkHit* locProjectedCDCTrkHit = NULL__null;
3157 map<DCDCTrkHit*, DCDCTrkHit*>::iterator locHitIterator = locProjectedStereoHitMap.find(hits[loc_l]);
3158 if(locHitIterator == locProjectedStereoHitMap.end())
3159 {
3160 // Clone the hit and set it's stereo-hit-position
3161 DVector3 locStereoHitPos;
3162 double locPhiStereo = 0.0, var_z = 9.9E9;
3163 locProjectedCDCTrkHit = Get_Resource_CDCTrkHit();
3164 *locProjectedCDCTrkHit = *hits[loc_l];
3165 //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
3166 //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
3167 if(Calc_StereoPosition(locProjectedCDCTrkHit->hit->wire, locCDCTrackCircle->fit, locStereoHitPos, var_z, locPhiStereo))
3168 locProjectedCDCTrkHit->dValidStereoHitPosFlag = true;
3169 locProjectedCDCTrkHit->dStereoHitPos = locStereoHitPos;
3170 locProjectedCDCTrkHit->var_z = var_z;
3171 locProjectedCDCTrkHit->dPhiStereo = locPhiStereo;
3172 dStereoHitNumUsedMap[locProjectedCDCTrkHit] = 1;
3173 }
3174 else
3175 {
3176 //hit was already projected onto this circle (e.g. in a different super layer seed), just reuse the results/memory
3177 locProjectedCDCTrkHit = locHitIterator->second;
3178 ++dStereoHitNumUsedMap[locProjectedCDCTrkHit];
3179 }
3180
3181 // Save the hit
3182 locProjectedHits.push_back(locProjectedCDCTrkHit);
3183 }
3184 locNewCDCSuperLayerSeed->dCDCRingSeeds[loc_i].hits = locProjectedHits;
3185 }
3186
3187 return locNewCDCSuperLayerSeed;
3188}
3189
3190//--------------------
3191// Calc_StereoPosition
3192//--------------------
3193bool DTrackCandidate_factory_CDC::Calc_StereoPosition(const DCDCWire *wire, const DHelicalFit* fit, DVector3 &pos, double &var_z, double& locPhiStereo, double d)
3194{
3195 // Calculate intersection point between circle and stereo wire
3196 DVector3 origin = wire->origin;
3197 DVector3 dir = (1./wire->udir.z())*wire->udir;
3198 double dx = origin.x() - fit->x0;
3199 double dy = origin.y() - fit->y0;
3200 double ux = dir.x();
3201 double uy = dir.y();
3202 double temp1 = ux*ux + uy*uy;
3203 double temp2 = ux*dy - uy*dx;
3204 double b = -ux*dx - uy*dy;
3205 double dr = fit->r0 - d;
3206 double r0_sq = dr*dr;
3207 double A = r0_sq*temp1 - temp2*temp2;
3208
3209 // Check that this wire intersects this circle
3210 if(A < 0.0)
3211 return false; // line along wire does not intersect circle, ever.
3212
3213 // Guess for variance for z: assume straw cell size??
3214 double temp = 1.6/sin(wire->stereo);
3215 var_z = temp*temp/12.;
3216
3217 // Calculate intersection points for the two roots
3218 double B = sqrt(A);
3219 double dz1 = (b - B)/temp1;
3220 double dz2 = (b + B)/temp1;
3221
3222 if(DEBUG_LEVEL > 15)
3223 cout<<"dz1="<<dz1<<" dz2="<<dz2<<endl;
3224
3225 // At this point we must decide which value of alpha to use.
3226 // For now, we just use the value closest to zero (i.e. closest to
3227 // the center of the wire).
3228 double dz = dz1;
3229 if(fabs(dz2) < fabs(dz1))
3230 dz = dz2;
3231
3232 // Compute the position for this hit
3233 pos = origin + dz*dir;
3234
3235 // distance along wire relative to origin
3236 double s = dz/cos(wire->stereo);
3237
3238 if(DEBUG_LEVEL > 15)
3239 cout<<"s="<<s<<" ring="<<wire->ring<<" straw="<<wire->straw<<" stereo="<<wire->stereo<<endl;
3240
3241 // Compute phi for the stereo wire
3242 DVector2 R(fit->x0, fit->y0);
3243 locPhiStereo = atan2(pos.Y() - R.Y(), pos.X() - R.X());
3244 R *= -1.0; // make R point from center of circle to beamline instead of other way around
3245 locPhiStereo -= R.Phi(); // make angle relative to beamline
3246
3247 // We want this to go either from 0 to +2pi for positive charge, or 0 to -2pi for negative.
3248 double phi_hi = fit->h > 0.0 ? +M_TWO_PI6.28318530717958647692 : 0.0;
3249 double phi_lo = fit->h > 0.0 ? 0.0 : -M_TWO_PI6.28318530717958647692;
3250 while(locPhiStereo < phi_lo)
3251 locPhiStereo += M_TWO_PI6.28318530717958647692;
3252 while(locPhiStereo > phi_hi)
3253 locPhiStereo -= M_TWO_PI6.28318530717958647692;
3254
3255 return true;
3256}
3257
3258//--------------------------
3259// Select_CDCSuperLayerSeeds
3260//--------------------------
3261bool DTrackCandidate_factory_CDC::Select_CDCSuperLayerSeeds(DCDCTrackCircle* locCDCTrackCircle, bool locFinalPassFlag)
3262{
3263 // If on initial pass (locFinalPassFlag = false):
3264 // Calculates the theta/z of the track for each possible combination of stereo super layer seeds.
3265 // The combination with the smallest chisq/ndf is selected, and the rest of the super layer seeds are deleted.
3266 // If there are no stereo hits, DO NOT reject the track, as Add_UnusedHits hasn't been called yet, and may find some.
3267
3268 // If on final pass (locFinalPassFlag = true):
3269 // Calculate the theta/z of the track using a subset of the remaining stereo hits
3270 // A subset is used to give the best-possible calculation of theta/z by ignoring hits where the circle-fit may be inaccurate
3271 // This is because the projection of the stereo hits onto the circle may be bad in this region, giving a bad theta/z result
3272 // If there are no stereo hits, reject the track.
3273
3274 // Select the best combinations of stereo hits and determine theta/z
3275 double locBestTheta = 0.0, locBestZ = TARGET_Z, locBestChiSqPerNDF = 9.9E99;
3276 deque<DCDCSuperLayerSeed*> locBestSuperLayerSeeds_Inner;
3277 deque<DCDCSuperLayerSeed*> locBestSuperLayerSeeds_Outer;
3278 bool locGoodStereoComboFoundFlag = false;
3279
3280 if((!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty()) && (!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty()))
3281 {
3282 //hits in both the inner & outer stereo super layers
3283 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
3284 {
3285 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_j)
3286 {
3287 //get the hits from this inner combination
3288 deque<DCDCTrkHit*> locComboHits;
3289 Select_ThetaZStereoHits(locCDCTrackCircle, loc_i, loc_j, locFinalPassFlag, locComboHits);
3290
3291 //Evaluate theta & z for this combination, returning the chisq/ndf from the fit
3292 double locTheta = 0.0, locZ = TARGET_Z, locChiSqPerNDF = 9.9E50;
3293 if(DEBUG_LEVEL > 5)
3294 cout << "in/out try theta/z, num stereo hits = " << locComboHits.size() << endl;
3295 if(!Find_ThetaZ(locCDCTrackCircle->fit, locComboHits, locTheta, locZ, locChiSqPerNDF))
3296 continue; //combo didn't work for some reason, try a different one
3297 if(!((locChiSqPerNDF < 1.0) || (locChiSqPerNDF > -1.0)))
3298 continue; // NaN
3299 locGoodStereoComboFoundFlag = true;
3300 if(DEBUG_LEVEL > 5)
3301 cout << "in/out good theta/z: theta, z, chisq, best-chisq = " << locTheta << ", " << locZ << ", " << locChiSqPerNDF << ", " << locBestChiSqPerNDF << endl;
3302 if(locChiSqPerNDF >= locBestChiSqPerNDF)
3303 continue;
3304 // This is the best combination of stereo seeds so far, save the results
3305 locBestSuperLayerSeeds_Inner.clear();
3306 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i].size(); ++loc_k)
3307 locBestSuperLayerSeeds_Inner.push_back(locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_k]);
3308 locBestSuperLayerSeeds_Outer.clear();
3309 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j].size(); ++loc_k)
3310 locBestSuperLayerSeeds_Outer.push_back(locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j][loc_k]);
3311 locBestTheta = locTheta;
3312 locBestZ = locZ;
3313 locBestChiSqPerNDF = locChiSqPerNDF;
3314 }
3315 }
3316 }
3317 else if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
3318 {
3319 //no hits in the outer super layers (or super layer 4 was missing)
3320 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
3321 {
3322 //get the hits from this inner combination
3323 deque<DCDCTrkHit*> locComboHits;
3324 Select_ThetaZStereoHits(locCDCTrackCircle, loc_i, -1, locFinalPassFlag, locComboHits);
3325
3326 //Evaluate theta & z for this combination, returning the chisq/ndf from the fit
3327 double locTheta = 0.0, locZ = TARGET_Z, locChiSqPerNDF = 9.9E50;
3328 if(DEBUG_LEVEL > 5)
3329 cout << "in-only try theta/z, num stereo hits = " << locComboHits.size() << endl;
3330 if(!Find_ThetaZ(locCDCTrackCircle->fit, locComboHits, locTheta, locZ, locChiSqPerNDF))
3331 continue; //combo didn't work for some reason, try a different one
3332 if(!((locChiSqPerNDF < 1.0) || (locChiSqPerNDF > -1.0)))
3333 continue; // NaN
3334 locGoodStereoComboFoundFlag = true;
3335 if(DEBUG_LEVEL > 5)
3336 cout << "in-only good theta/z: theta, z, chisq, best-chisq = " << locTheta << ", " << locZ << ", " << locChiSqPerNDF << ", " << locBestChiSqPerNDF << endl;
3337 if(locChiSqPerNDF >= locBestChiSqPerNDF)
3338 continue;
3339 // This is the best combination of stereo seeds so far, save the results
3340 locBestSuperLayerSeeds_Inner.clear();
3341 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i].size(); ++loc_k)
3342 locBestSuperLayerSeeds_Inner.push_back(locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_k]);
3343 locBestSuperLayerSeeds_Outer.clear();
3344 locBestTheta = locTheta;
3345 locBestZ = locZ;
3346 locBestChiSqPerNDF = locChiSqPerNDF;
3347 }
3348 }
3349 else if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
3350 {
3351 // no hits in the inner super layers: e.g. decay product (e.g. p) of a long-lived decaying neutral particle (e.g. lambda)
3352 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_j)
3353 {
3354 //get the hits from this inner combination
3355 deque<DCDCTrkHit*> locComboHits;
3356 Select_ThetaZStereoHits(locCDCTrackCircle, -1, loc_j, locFinalPassFlag, locComboHits);
3357
3358 //Evaluate theta & z for this combination, returning the chisq/ndf from the fit
3359 double locTheta = 0.0, locZ = TARGET_Z, locChiSqPerNDF = 9.9E50;
3360 if(DEBUG_LEVEL > 5)
3361 cout << "out-only try theta/z, num stereo hits = " << locComboHits.size() << endl;
3362 if(!Find_ThetaZ(locCDCTrackCircle->fit, locComboHits, locTheta, locZ, locChiSqPerNDF))
3363 continue; //combo didn't work for some reason, try a different one
3364 if(!((locChiSqPerNDF < 1.0) || (locChiSqPerNDF > -1.0)))
3365 continue; // NaN
3366 locGoodStereoComboFoundFlag = true;
3367 if(DEBUG_LEVEL > 5)
3368 cout << "out-only good theta/z: theta, z, chisq, best-chisq = " << locTheta << ", " << locZ << ", " << locChiSqPerNDF << ", " << locBestChiSqPerNDF << endl;
3369 if(locChiSqPerNDF >= locBestChiSqPerNDF)
3370 continue;
3371 // This is the best combination of stereo seeds so far, save the results
3372 locBestSuperLayerSeeds_Inner.clear();
3373 locBestSuperLayerSeeds_Outer.clear();
3374 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j].size(); ++loc_k)
3375 locBestSuperLayerSeeds_Outer.push_back(locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_j][loc_k]);
3376 locBestTheta = locTheta;
3377 locBestZ = locZ;
3378 locBestChiSqPerNDF = locChiSqPerNDF;
3379 }
3380 }
3381 else //no stereo hits
3382 return (!locFinalPassFlag); //return true if don't wan't to filter, false if you do
3383
3384 //save the results to the track circle
3385 locCDCTrackCircle->dTheta = locBestTheta;
3386 locCDCTrackCircle->dVertexZ = locBestZ;
3387 double locNumStereoSuperLayers = double(locBestSuperLayerSeeds_Inner.size() + locBestSuperLayerSeeds_Outer.size());
3388 locCDCTrackCircle->dWeightedChiSqPerDF_Stereo = locBestChiSqPerNDF/(locNumStereoSuperLayers*locNumStereoSuperLayers);
3389
3390 set<DCDCSuperLayerSeed*> locAlreadyRecycledSuperLayerSeeds; //a seed can appear in more than one combo: don't recycle the same memory more than once!!
3391
3392 // recycle the unused super layer seeds and store only the best ones: inner
3393 if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
3394 {
3395 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
3396 {
3397 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i].size(); ++loc_j)
3398 {
3399 DCDCSuperLayerSeed* locCDCSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i][loc_j];
3400 if(locAlreadyRecycledSuperLayerSeeds.find(locCDCSuperLayerSeed) != locAlreadyRecycledSuperLayerSeeds.end())
3401 continue; //already recycled!
3402 bool locKeepSuperLayerSeed = false;
3403 for(size_t loc_k = 0; loc_k < locBestSuperLayerSeeds_Inner.size(); ++loc_k)
3404 {
3405 if(locBestSuperLayerSeeds_Inner[loc_k] != locCDCSuperLayerSeed)
3406 continue;
3407 locKeepSuperLayerSeed = true; //one of the best, don't recycle!!
3408 break;
3409 }
3410 if(locKeepSuperLayerSeed)
3411 continue;
3412 Recycle_DCDCSuperLayerSeed(locCDCSuperLayerSeed); //no longer in use
3413 locAlreadyRecycledSuperLayerSeeds.insert(locCDCSuperLayerSeed);
3414 }
3415 }
3416 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.clear();
3417 if(locGoodStereoComboFoundFlag)
3418 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.push_back(locBestSuperLayerSeeds_Inner);
3419 }
3420 locAlreadyRecycledSuperLayerSeeds.clear();
3421
3422 // recycle the unused super layer seeds and store only the best ones: outer
3423 if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
3424 {
3425 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_i)
3426 {
3427 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i].size(); ++loc_j)
3428 {
3429 DCDCSuperLayerSeed* locCDCSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i][loc_j];
3430 if(locAlreadyRecycledSuperLayerSeeds.find(locCDCSuperLayerSeed) != locAlreadyRecycledSuperLayerSeeds.end())
3431 continue; //already recycled!
3432 bool locKeepSuperLayerSeed = false;
3433 for(size_t loc_k = 0; loc_k < locBestSuperLayerSeeds_Outer.size(); ++loc_k)
3434 {
3435 if(locBestSuperLayerSeeds_Outer[loc_k] != locCDCSuperLayerSeed)
3436 continue;
3437 locKeepSuperLayerSeed = true; //one of the best, don't recycle!!
3438 break;
3439 }
3440 if(locKeepSuperLayerSeed)
3441 continue;
3442 Recycle_DCDCSuperLayerSeed(locCDCSuperLayerSeed); //no longer in use
3443 locAlreadyRecycledSuperLayerSeeds.insert(locCDCSuperLayerSeed);
3444 }
3445 }
3446 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.clear();
3447 if(locGoodStereoComboFoundFlag)
3448 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.push_back(locBestSuperLayerSeeds_Outer);
3449 }
3450
3451 return locGoodStereoComboFoundFlag;
3452}
3453
3454//------------------------
3455// Select_ThetaZStereoHits
3456//------------------------
3457void DTrackCandidate_factory_CDC::Select_ThetaZStereoHits(const DCDCTrackCircle* locCDCTrackCircle, int locInnerSeedSeriesIndex, int locOuterSeedSeriesIndex, bool locFinalPassFlag, deque<DCDCTrkHit*>& locComboHits)
3458{
3459 //tracks at the edges of the CDC's phase space OFTEN fail because the circle-fit is not perfect
3460 //this causes the projected-hit-position on the circle of the stereo hits to be incorrect
3461 //which then causes the calculated theta/z to be bad, which causes the momentum magnitude to be bad
3462 //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
3463 //this is because the circle fit is extrapolated out to SL5 & SL6 and the errors are much larger
3464 //therefore, you must be VERY careful when selecting which stereo hits to use for the final calculation of theta & z
3465 //for the initial calculation: use all stereo hits: the initial calculation is intended to select which stereo super layer seeds are best, nothing more
3466
3467 locComboHits.clear();
3468
3469 // Get super layer seeds for this combination
3470 deque<DCDCSuperLayerSeed*> locSuperLayerSeeds;
3471 if(locInnerSeedSeriesIndex >= 0)
3472 {
3473 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[locInnerSeedSeriesIndex].size(); ++loc_k)
3474 locSuperLayerSeeds.push_back(locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[locInnerSeedSeriesIndex][loc_k]);
3475 }
3476 if(locOuterSeedSeriesIndex >= 0)
3477 {
3478 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[locOuterSeedSeriesIndex].size(); ++loc_k)
3479 locSuperLayerSeeds.push_back(locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[locOuterSeedSeriesIndex][loc_k]);
3480 }
3481
3482 //select initial hits: prune hits that don't intersect the circle
3483 deque<DCDCTrkHit*> locHits;
3484 map<unsigned int, deque<DCDCTrkHit*> > locHitsBySuperLayer; //key is super layer
3485 unsigned int locTotalNumStereoHits = 0;
3486 for(size_t loc_k = 0; loc_k < locSuperLayerSeeds.size(); ++loc_k)
3487 {
3488 locSuperLayerSeeds[loc_k]->Get_Hits(locHits);
3489 for(deque<DCDCTrkHit*>::iterator locIterator = locHits.begin(); locIterator != locHits.end();)
3490 {
3491 if((*locIterator)->dValidStereoHitPosFlag)
3492 ++locIterator;
3493 else
3494 locIterator = locHits.erase(locIterator);
3495 }
3496 locHitsBySuperLayer[locSuperLayerSeeds[loc_k]->dSuperLayer] = locHits;
3497 locTotalNumStereoHits += locHits.size();
3498 }
3499
3500 // see if no more pruning is necessary
3501 // don't prune anymore if on initial pass, or if very few stereo hits
3502 if((!locFinalPassFlag) || (locTotalNumStereoHits <= MIN_PRUNED_STEREO_HITS))
3503 {
3504 // no more pruning, add hits to locComboHits and return
3505 map<unsigned int, deque<DCDCTrkHit*> >::iterator locMapIterator;
3506 for(locMapIterator = locHitsBySuperLayer.begin(); locMapIterator != locHitsBySuperLayer.end(); ++locMapIterator)
3507 locComboHits.insert(locComboHits.end(), locMapIterator->second.begin(), locMapIterator->second.end());
3508 if(DEBUG_LEVEL > 10)
3509 cout << "no more pruning, total num stereo hits = " << locTotalNumStereoHits << endl;
3510 return; //either on first pass (eval'ing which stereo seed is best), or not enough hits to prune: return
3511 }
3512
3513 // Now, select the stereo hits whose projection onto the cirlce-fit are closest to the axial hits
3514 // the closer the stereo hits are to the axial hits, the better the estimation of theta/z will be
3515
3516 //calc delta-phi for all remaining hits and sort them
3517 //delta-phi: between the intersection-of-the-stereo-hit-with-the-circle and the nearest axial hits
3518 deque<pair<DCDCTrkHit*, double> > locDeltaPhis;
3519 for(size_t loc_k = 0; loc_k < locSuperLayerSeeds.size(); ++loc_k)
3520 {
3521 unsigned int locSuperLayer = locSuperLayerSeeds[loc_k]->dSuperLayer;
3522 Calc_StereoHitDeltaPhis(locSuperLayer, locHitsBySuperLayer[locSuperLayer], locCDCTrackCircle, locDeltaPhis);
3523 }
3524 sort(locDeltaPhis.begin(), locDeltaPhis.end(), CDCSort_DeltaPhis);
3525
3526 if(locDeltaPhis.size() <= MIN_PRUNED_STEREO_HITS)
3527 {
3528 for(size_t loc_k = 0; loc_k < locDeltaPhis.size(); ++loc_k)
3529 locComboHits.push_back(locDeltaPhis[loc_k].first);
3530 return;
3531 }
3532
3533 // take at least the "MIN_PRUNED_STEREO_HITS" hits with the smallest delta_phi
3534 double locMaxHitDeltaPhi = locDeltaPhis[MIN_PRUNED_STEREO_HITS - 1].second;
3535
3536 // now, potentially expand the max-delta-phi range in certain cases:
3537 double locDeltaPhiRangeExtension = 0.0;
3538 //if first statement below is true, want all the stereo hits:
3539 //track was matched to another track circle as a spiral turn, and it turns in its last axial layer (4 or 7)
3540 //because it is turning sharply, as much info/hits as possible is needed to give an accurate theta
3541 //however, if it was turning in a stereo layer, then the sharpest part of the turn was not included in the circle fit
3542 //in this case the hit-projections onto the circle are probably way off, so only expand to pi if turning on axial layer
3543 //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
3544 //in this case, all stereo hits within a reasonable distance (10 degrees) from the track circle are probably OK.
3545 //note: expanding beyond 10-15 degrees kills candidates at theta >= 120:
3546 //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
3547 //if neither statement below is true, then the track likely spiraled in a stereo super layer:
3548 //don't trust the stereo information as much: only take stereo hits very close to the axial hits
3549
3550 unsigned int locLastSuperLayer = locCDCTrackCircle->Get_LastSuperLayerSeed()->dSuperLayer;
3551 if(((locLastSuperLayer == 4) || (locLastSuperLayer == 7)) && (locCDCTrackCircle->dSpiralTurnRing != -1))
3552 locDeltaPhiRangeExtension = M_PI3.14159265358979323846; //spiral turn on axial layer: all stereo hits good
3553 else if(locCDCTrackCircle->fit->r0 > 65.0/2.0) //BCAL is at r = ~65
3554 locDeltaPhiRangeExtension = 10.0; //unlikely to spiral, all stereo hits reasonably close are good
3555 else
3556 locDeltaPhiRangeExtension = 5.0; //likely spiraled, trust stereo information less
3557 locMaxHitDeltaPhi += locDeltaPhiRangeExtension;
3558
3559 if(DEBUG_LEVEL > 10)
3560 cout << "prune with max delta-phi, fit circle r0 = " << locMaxHitDeltaPhi << ", " << locCDCTrackCircle->fit->r0 << endl;
3561 size_t locDeltaPhiIndex = 0;
3562 // add stereo hits to locComboHits whose projection onto the circle fit are within locMaxHitDeltaPhi of the nearest axial hit phi
3563 for(locDeltaPhiIndex = 0; locDeltaPhiIndex < locDeltaPhis.size(); ++locDeltaPhiIndex)
3564 {
3565 if(locDeltaPhis[locDeltaPhiIndex].second > locMaxHitDeltaPhi)
3566 break;
3567 locComboHits.push_back(locDeltaPhis[locDeltaPhiIndex].first);
3568 }
3569
3570 //make sure to have at least one wire from each super layer
3571 // this is especially useful for spiral turns in SL6, where the majority of the theta-constraining information comes from SL5 and SL6
3572 // you don't want very many of these hits because they can throw you off, but having at least one really helps
3573 // this is experimental: it may not be necessary if the above locMaxHitDeltaPhi section is better fine-tuned
3574
3575 // to keep track of which super layers need hits, delete keys from locHitsBySuperLayer map if hits from them are already selected
3576 map<unsigned int, deque<DCDCTrkHit*> >::iterator locMapIterator;
3577 for(size_t loc_i = 0; loc_i < locComboHits.size(); ++loc_i)
3578 {
3579 unsigned int locSuperLayer = (locComboHits[loc_i]->hit->wire->ring - 1)/4 + 1;
3580 locMapIterator = locHitsBySuperLayer.find(locSuperLayer);
3581 if(locMapIterator == locHitsBySuperLayer.end())
3582 continue; //already have a hit of that type
3583 locHitsBySuperLayer.erase(locMapIterator); //have a hit of this type
3584 if(locHitsBySuperLayer.empty())
3585 break;
3586 }
3587
3588 //locHitsBySuperLayer now only contains the keys of super layers that don't have hits yet: loop over them
3589 for(locMapIterator = locHitsBySuperLayer.begin(); locMapIterator != locHitsBySuperLayer.end(); ++locMapIterator)
3590 {
3591 // search for the hit with the lowest delta-phi from this (locMapIterator->first) super layer
3592 for(size_t loc_i = locDeltaPhiIndex; loc_i < locDeltaPhis.size(); ++loc_i) //everything before locDeltaPhiIndex was already included
3593 {
3594 unsigned int locSuperLayer = (locDeltaPhis[loc_i].first->hit->wire->ring - 1)/4 + 1;
3595 if(locSuperLayer != locMapIterator->first)
3596 continue;
3597 locComboHits.push_back(locDeltaPhis[loc_i].first); //use best hit on this super layer
3598 if(DEBUG_LEVEL > 10)
3599 cout << "Add stereo hit on SL" << locSuperLayer << ": ring, straw = " << locDeltaPhis[loc_i].first->hit->wire->ring << ", " << locDeltaPhis[loc_i].first->hit->wire->straw << endl;
3600 break;
3601 }
3602 }
3603
3604 if(DEBUG_LEVEL > 10)
3605 cout << "final #hits = " << locComboHits.size() << endl;
3606}
3607
3608//------------------------
3609// Calc_StereoHitDeltaPhis
3610//------------------------
3611void DTrackCandidate_factory_CDC::Calc_StereoHitDeltaPhis(unsigned int locSuperLayer, deque<DCDCTrkHit*>& locHits, const DCDCTrackCircle* locCDCTrackCircle, deque<pair<DCDCTrkHit*, double> >& locDeltaPhis)
3612{
3613 // calc delta-phi for hits: distance from projected-stereo-hit-position to the nearest axial hits
3614 // because the circle fit is not perfect, the stereo hit position gets progessively worse the sharper the track is turning
3615 // this screws up the theta/z calculation, so just ignore the hits that are the farthest away
3616 // 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
3617
3618 if(DEBUG_LEVEL > 10)
3619 cout << "Calc_StereoHitDeltaPhis, SL = " << locSuperLayer << ", #hits = " << locHits.size() << endl;
3620
3621 //get the axial super layer seeds nearest this seed:
3622 DCDCSuperLayerSeed* locPriorAxialSuperLayerSeed = NULL__null;
3623 DCDCSuperLayerSeed* locNextAxialSuperLayerSeed = NULL__null;
3624 for(size_t loc_k = 0; loc_k < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_k)
3625 {
3626 if(locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_k]->dSuperLayer < locSuperLayer)
3627 locPriorAxialSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_k];
3628 else if((locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_k]->dSuperLayer > locSuperLayer) && (locNextAxialSuperLayerSeed == NULL__null))
3629 locNextAxialSuperLayerSeed = locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_k];
3630 }
3631
3632 //get the rings in the axial super layer seeds nearest this stereo seed:
3633 DCDCRingSeed* locPriorAxialRingSeed = NULL__null;
3634 if(locPriorAxialSuperLayerSeed != NULL__null)
3635 {
3636 locPriorAxialRingSeed = &(locPriorAxialSuperLayerSeed->dCDCRingSeeds.back());
3637 if(DEBUG_LEVEL > 10)
3638 cout << "Prior axial ring = " << locPriorAxialRingSeed->ring << endl;
3639 }
3640 DCDCRingSeed* locNextAxialRingSeed = NULL__null;
3641 if(locNextAxialSuperLayerSeed != NULL__null)
3642 {
3643 locNextAxialRingSeed = &(locNextAxialSuperLayerSeed->dCDCRingSeeds.front());
3644 if(DEBUG_LEVEL > 10)
3645 cout << "Next axial ring = " << locNextAxialRingSeed->ring << endl;
3646 }
3647 if((locPriorAxialRingSeed == NULL__null) && (locNextAxialRingSeed == NULL__null))
3648 return; //no axial hits: shoudldn't be possible ...
3649
3650 // calculate min-delta-phi for each hit (to the nearest axial ring seed)
3651 for(size_t loc_i = 0; loc_i < locHits.size(); ++loc_i)
3652 {
3653 deque<DCDCTrkHit*> locTempDeque(1, locHits[loc_i]);
3654 double locMinDeltaPhi = M_PI3.14159265358979323846;
3655 //compare to prior axial ring
3656 if(locPriorAxialRingSeed != NULL__null)
3657 {
3658 double locDeltaPhi = MinDeltaPhi(locPriorAxialRingSeed->hits, locTempDeque);
3659 if(locDeltaPhi < locMinDeltaPhi)
3660 locMinDeltaPhi = locDeltaPhi;
3661 }
3662 //compare to next axial ring
3663 if(locNextAxialRingSeed != NULL__null)
3664 {
3665 double locDeltaPhi = MinDeltaPhi(locTempDeque, locNextAxialRingSeed->hits);
3666 if(locDeltaPhi < locMinDeltaPhi)
3667 locMinDeltaPhi = locDeltaPhi;
3668 }
3669 locMinDeltaPhi *= 180.0/M_PI3.14159265358979323846;
3670 if(DEBUG_LEVEL > 10)
3671 cout << "Ring, Straw, min delta phi = " << locHits[loc_i]->hit->wire->ring << ", " << locHits[loc_i]->hit->wire->straw << ", " << locMinDeltaPhi << endl;
3672 //store the minimum
3673 locDeltaPhis.push_back(pair<DCDCTrkHit*, double>(locHits[loc_i], locMinDeltaPhi));
3674 }
3675}
3676
3677//------------
3678// MinDeltaPhi
3679//------------
3680double DTrackCandidate_factory_CDC::MinDeltaPhi(const deque<DCDCTrkHit*>& locInnerSeedHits, const deque<DCDCTrkHit*>& locOuterSeedHits)
3681{
3682 /// 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.
3683 /// First it checks if the two seeds overlap in phi: if so, then return 0
3684 /// Otherwise, only the first and last hits of the adjacent rings between each seed's hit list are used.
3685 /// to calculate a maximum of 4 delta-phis (minimum of 1) of which, the smallest is returned.
3686 if(locInnerSeedHits.empty() || locOuterSeedHits.empty())
3687 {
3688 cout << "Number of seed hits 0! (Ninner = " << locInnerSeedHits.size() << " ,Nouter = " << locOuterSeedHits.size() << ")" << endl;
3689 return M_PI3.14159265358979323846;
3690 }
3691
3692 DCDCTrkHit* locInnermostRingFirstStrawHit = locInnerSeedHits.front();
3693 DCDCTrkHit* locInnermostRingLastStrawHit = locInnerSeedHits.back();
3694 DCDCTrkHit* locOutermostRingFirstStrawHit = locOuterSeedHits.front();
3695 DCDCTrkHit* locOutermostRingLastStrawHit = locOuterSeedHits.back();
3696
3697 //see if seeds overlap in phi
3698 float locInnermostRingFirstStrawPhi = locInnermostRingFirstStrawHit->hit->wire->phi;
3699 float locInnermostRingLastStrawPhi = locInnermostRingLastStrawHit->hit->wire->phi;
3700 float locOutermostRingFirstStrawPhi = locOutermostRingFirstStrawHit->hit->wire->phi;
3701 float locOutermostRingLastStrawPhi = locOutermostRingLastStrawHit->hit->wire->phi;
3702 if(DEBUG_LEVEL > 100)
3703 cout << "inner ring: ring, first/last straws & phis = " << locInnermostRingFirstStrawHit->hit->wire->ring << ", " << locInnermostRingFirstStrawHit->hit->wire->straw << ", " << locInnermostRingLastStrawHit->hit->wire->straw << ", " << locInnermostRingFirstStrawPhi << ", " << locInnermostRingLastStrawPhi << endl;
3704 if(DEBUG_LEVEL > 100)
3705 cout << "outer ring: ring, first/last straws & phis = " << locOutermostRingFirstStrawHit->hit->wire->ring << ", " << locOutermostRingFirstStrawHit->hit->wire->straw << ", " << locOutermostRingLastStrawHit->hit->wire->straw << ", " << locOutermostRingFirstStrawPhi << ", " << locOutermostRingLastStrawPhi << endl;
3706
3707 //account for phi = 0/2pi boundary
3708 bool locInnerRingCrossesBoundaryFlag = (locInnermostRingLastStrawPhi < locInnermostRingFirstStrawPhi);
3709 bool locOuterRingCrossesBoundaryFlag = (locOutermostRingLastStrawPhi < locOutermostRingFirstStrawPhi);
3710 if(DEBUG_LEVEL > 100)
3711 cout << "in/out boundary flags = " << locInnerRingCrossesBoundaryFlag << ", " << locOuterRingCrossesBoundaryFlag << endl;
3712 if(locOuterRingCrossesBoundaryFlag)
3713 locOutermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
3714 if(locInnerRingCrossesBoundaryFlag)
3715 locInnermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
3716 if(locOuterRingCrossesBoundaryFlag & (!locInnerRingCrossesBoundaryFlag) && ((locOutermostRingLastStrawPhi - locInnermostRingLastStrawPhi) > M_PI3.14159265358979323846))
3717 {
3718 locInnermostRingFirstStrawPhi += M_TWO_PI6.28318530717958647692;
3719 locInnermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
3720 }
3721 if(locInnerRingCrossesBoundaryFlag & (!locOuterRingCrossesBoundaryFlag) && ((locInnermostRingLastStrawPhi - locOutermostRingLastStrawPhi) > M_PI3.14159265358979323846))
3722 {
3723 locOutermostRingFirstStrawPhi += M_TWO_PI6.28318530717958647692;
3724 locOutermostRingLastStrawPhi += M_TWO_PI6.28318530717958647692;
3725 }
3726
3727 if(DEBUG_LEVEL > 100)
3728 cout << "final inner ring: ring, first/last straws & phis = " << locInnermostRingFirstStrawHit->hit->wire->ring << ", " << locInnermostRingFirstStrawHit->hit->wire->straw << ", " << locInnermostRingLastStrawHit->hit->wire->straw << ", " << locInnermostRingFirstStrawPhi << ", " << locInnermostRingLastStrawPhi << endl;
3729 if(DEBUG_LEVEL > 100)
3730 cout << "final outer ring: ring, first/last straws & phis = " << locOutermostRingFirstStrawHit->hit->wire->ring << ", " << locOutermostRingFirstStrawHit->hit->wire->straw << ", " << locOutermostRingLastStrawHit->hit->wire->straw << ", " << locOutermostRingFirstStrawPhi << ", " << locOutermostRingLastStrawPhi << endl;
3731
3732 if((locOutermostRingFirstStrawPhi >= locInnermostRingFirstStrawPhi) && (locOutermostRingFirstStrawPhi <= locInnermostRingLastStrawPhi))
3733 return 0.0;
3734 if((locOutermostRingLastStrawPhi >= locInnermostRingFirstStrawPhi) && (locOutermostRingLastStrawPhi <= locInnermostRingLastStrawPhi))
3735 return 0.0;
3736 if((locInnermostRingFirstStrawPhi >= locOutermostRingFirstStrawPhi) && (locInnermostRingFirstStrawPhi <= locOutermostRingLastStrawPhi))
3737 return 0.0; //4th case not needed. this case only needed if innermost ring is one wire across
3738
3739 //make all 4 comparisons between hits
3740 double locDeltaPhi, locMinDeltaPhi;
3741 locMinDeltaPhi = fabs(locInnermostRingFirstStrawPhi - locOutermostRingFirstStrawPhi);
3742 if(locMinDeltaPhi > M_PI3.14159265358979323846)
3743 locMinDeltaPhi = fabs(locMinDeltaPhi - M_TWO_PI6.28318530717958647692);
3744 if(locOutermostRingFirstStrawHit != locOutermostRingLastStrawHit)
3745 {
3746 locDeltaPhi = fabs(locInnermostRingFirstStrawPhi - locOutermostRingLastStrawPhi);
3747 if(locDeltaPhi > M_PI3.14159265358979323846)
3748 locDeltaPhi = fabs(locDeltaPhi - M_TWO_PI6.28318530717958647692);
3749 if(locDeltaPhi < locMinDeltaPhi)
3750 locMinDeltaPhi = locDeltaPhi;
3751 }
3752 if(locInnermostRingFirstStrawHit == locInnermostRingLastStrawHit)
3753 return locMinDeltaPhi;
3754
3755 locDeltaPhi = fabs(locInnermostRingLastStrawPhi - locOutermostRingFirstStrawPhi);
3756 if(locDeltaPhi > M_PI3.14159265358979323846)
3757 locDeltaPhi = fabs(locDeltaPhi - M_TWO_PI6.28318530717958647692);
3758 if(locDeltaPhi < locMinDeltaPhi)
3759 locMinDeltaPhi = locDeltaPhi;
3760 if(locOutermostRingFirstStrawHit != locOutermostRingLastStrawHit)
3761 {
3762 locDeltaPhi = fabs(locInnermostRingLastStrawPhi - locOutermostRingLastStrawPhi);
3763 if(locDeltaPhi > M_PI3.14159265358979323846)
3764 locDeltaPhi = fabs(locDeltaPhi - M_TWO_PI6.28318530717958647692);
3765 if(locDeltaPhi < locMinDeltaPhi)
3766 locMinDeltaPhi = locDeltaPhi;
3767 }
3768
3769 return locMinDeltaPhi;
3770}
3771
3772//------------
3773// Find_ThetaZ
3774//------------
3775bool DTrackCandidate_factory_CDC::Find_ThetaZ(const DHelicalFit* locFit, const deque<DCDCTrkHit*>& locStereoHits, double& locTheta, double& locZ, double& locChiSqPerNDF)
3776{
3777 // Calculate theta/z for the input stereo hits
3778 if(locStereoHits.empty())
3779 return false;
3780
3781 if(Find_ThetaZ_Regression(locFit, locStereoHits, locTheta, locZ, locChiSqPerNDF))
3782 return true;
3783 double locThetaMin, locThetaMax;
3784
3785 // Regression fit failed, try using histogram methods
3786 bool locThetaOKFlag = Find_Theta(locFit, locStereoHits, locTheta, locThetaMin, locThetaMax, locChiSqPerNDF);
3787 if(locThetaOKFlag)
3788 {
3789 if(Find_Z(locFit, locStereoHits, locThetaMin, locThetaMax, locZ))
3790 return true;
3791 }
3792
3793 // Histogram methods failed.
3794
3795 // Assume that the track came from the center of the target
3796 locChiSqPerNDF = 9.9E8;
3797 locZ = TARGET_Z;
3798 if(locThetaOKFlag)
3799 return true;
3800
3801 // Use a point in one of the stereo layers to estimate tanl
3802 double x = locStereoHits[0]->dStereoHitPos.X();
3803 double y = locStereoHits[0]->dStereoHitPos.Y();
3804 double tworc = 2.0*locFit->r0;
3805 double ratio = sqrt(x*x + y*y)/tworc;
3806 if(ratio >= 1.0)
3807 return false;
3808
3809 double tanl = (locStereoHits[0]->dStereoHitPos.Z() - locZ)/(tworc*asin(ratio));
3810 locTheta = M_PI_21.57079632679489661923 - atan(tanl);
3811 return true;
3812}
3813
3814//-----------------------
3815// Find_ThetaZ_Regression
3816//-----------------------
3817// Linear regression to find tan(lambda) and z_vertex.
3818// This method assumes that there are errors in both the z positions and
3819// the arc lengths.
3820// Algorithm from Numerical Recipes in C (2nd. ed.), pp. 668-669.
3821bool DTrackCandidate_factory_CDC::Find_ThetaZ_Regression(const DHelicalFit* locFit, const deque<DCDCTrkHit*>& locStereoHits, double& locTheta, double& locZ, double& locChiSqPerNDF)
3822{
3823 if(DEBUG_LEVEL > 3)
3824 cout<<"Finding theta and z via linear regression method."<<endl;
3825
3826 if(locStereoHits.empty() || (!(locFit->normal.Mag() > 0.0)))
3827 return false;
3828
3829 // Vector of intersections between the circle and the stereo wires
3830 vector<intersection_t> intersections;
3831 for(size_t m = 0; m < locStereoHits.size(); ++m)
3832 {
3833 DCDCTrkHit* trkhit = locStereoHits[m];
3834
3835 //DVector3_with_perp intersection;
3836 intersection_t intersection;
3837 intersection.x = trkhit->dStereoHitPos.X();
3838 intersection.y = trkhit->dStereoHitPos.Y();
3839 intersection.perp2 = intersection.x*intersection.x + intersection.y*intersection.y;
3840 intersection.z = trkhit->dStereoHitPos.Z();
3841 intersection.var_z = trkhit->var_z;
3842 intersections.push_back(intersection);
3843 }
3844
3845 // Now, sort the entries
3846 sort(intersections.begin(), intersections.end(), CDCSort_Intersections);
3847
3848 // Compute the arc lengths between the origin in x and y and (xi,yi)
3849 vector<double> arclengths(intersections.size());
3850 vector<double> ratios(intersections.size());
3851 double xc = locFit->x0;
3852 double yc = locFit->y0;
3853 double rc = locFit->r0;
3854 double two_rc = 2.*rc;
3855
3856 // Find POCA to beam line
3857 double myphi = atan2(yc, xc);
3858 double y0 = yc - rc*sin(myphi);
3859 double x0 = xc - rc*cos(myphi);
3860
3861 // Arc length to first measurement
3862 double diffx = intersections[0].x - x0;
3863 double diffy = intersections[0].y - y0;
3864 double chord = sqrt(diffx*diffx + diffy*diffy);
3865 double ratio = chord/two_rc;
3866 double s = (ratio < 1.) ? two_rc*asin(ratio) : M_PI_21.57079632679489661923*two_rc;
3867 arclengths[0] = s;
3868 ratios[0] = ratio;
3869
3870 // Find arc lengths for the rest of the stereo hits
3871 for(size_t m = 1; m < arclengths.size(); ++m)
3872 {
3873 diffx = intersections[m].x - intersections[m - 1].x;
3874 diffy = intersections[m].y - intersections[m - 1].y;
3875 chord = sqrt(diffx*diffx + diffy*diffy);
3876 ratio = chord/two_rc;
3877 if(ratio > 0.999)
3878 return false;
3879 double ds = two_rc*asin(ratio);
3880 s += ds;
3881 arclengths[m] = s;
3882 ratios[m] = ratio;
3883 }
3884
3885 //Linear regression to find z0, tanl
3886 double tanl = 0.,z0 = 0.;
3887 if(arclengths.size() > 1) // Do fit only if have more than one measurement
3888 {
3889 DCDCLineFit fit;
3890 size_t n = fit.n = intersections.size();
3891 fit.s.resize(n);
3892 fit.var_s.resize(n);
3893 fit.z.resize(n);
3894 fit.var_z.resize(n);
3895 fit.w.resize(n);
3896
3897 // Find average variances for z and s
3898 double avg_var_s = 0., avg_var_z = 0.;
3899 double var_r = 1.6*1.6/12.; // assume cell size
3900 for (size_t m = 0; m < n; ++m)
3901 {
3902 fit.s[m] = arclengths[m];
3903 fit.var_s[m] = var_r/(1. - ratios[m]*ratios[m]);
3904
3905 avg_var_s += fit.var_s[m];
3906 avg_var_z += intersections[m].var_z;
3907
3908 if(DEBUG_LEVEL>5)
3909 cout<<"Using CDC hit "<<m<<" z="<<intersections[m].z << " s=" << arclengths[m] <<endl;
3910 }
3911
3912 // Scale z errors according to the ratio of the average variances
3913 double scale2 = avg_var_s/avg_var_z;
3914 double scale = sqrt(scale2);
3915 vector<double> weight(n);
3916 for (size_t m = 0; m < n; ++m)
3917 {
3918 fit.z[m] = scale*intersections[m].z;
3919 fit.var_z[m] = scale2*intersections[m].var_z;
3920 weight[m] = fit.var_s[m] + fit.var_z[m];
3921 }
3922
3923 // Perform preliminary fit to find the (scaled) slope tanl
3924 double sumv=0., sumx=0.;
3925 double sumy=0., sumxx=0., sumxy=0.;
3926 for(size_t m = 0; m < n; ++m)
3927 {
3928 //double temp = 1./var_z[m];
3929 double temp = 1./weight[m];
3930 sumv += temp;
3931 sumx += arclengths[m]*temp;
3932 sumy += fit.z[m]*temp;
3933 sumxx += arclengths[m]*arclengths[m]*temp;
3934 sumxy += arclengths[m]*fit.z[m]*temp;
3935 }
3936 double Delta = sumv*sumxx - sumx*sumx;
3937 if(!(fabs(Delta) > 0.0))
3938 return false;
3939
3940 tanl = (sumv*sumxy - sumx*sumy)/Delta;
3941 fit.z0 = (sumxx*sumy - sumx*sumxy)/Delta;
3942
3943 // Convert tanl to an angle and create two other reference angles
3944 double angle[3];
3945 angle[0] = 0.;
3946 angle[1] = atan(tanl);
3947 angle[2] = 1.571;
3948 // Compute chi^2 values for line fits with these three angles
3949 double ch[3];
3950 for (unsigned int m = 0; m < 3; ++m)
3951 ch[m] = fit.ChiXY(angle[m]);
3952
3953 // Bracket the minimum chi^2
3954 fit.BracketMinimumChisq(angle[0], angle[1], angle[2], ch[0], ch[1], ch[2]);
3955 // Find the minimum chi^2 using Brent's method and compute the best value for lambda
3956 double lambda = 0.;
3957 locChiSqPerNDF = fit.FindMinimumChisq(angle[0], angle[1], angle[2], lambda)/2.0; //2 degrees of freedom
3958 // Undo the scaling
3959 z0 = fit.z0/scale;
3960 tanl = tan(lambda)/scale;
3961 }
3962 else
3963 {
3964 z0 = TARGET_Z;
3965 tanl = (intersections[0].z - z0)/arclengths[0];
3966 locChiSqPerNDF = 9.9E9; //only two hits: technically is zero, but if possible want to pick a group of stereo hits with more hits
3967 }
3968
3969 locTheta = M_PI_21.57079632679489661923 - atan(tanl);
3970 locZ = z0;
3971
3972 return true;
3973}
3974
3975//-----------
3976// Find_Theta
3977//-----------
3978bool DTrackCandidate_factory_CDC::Find_Theta(const DHelicalFit* locFit, const deque<DCDCTrkHit*>& locStereoHits, double& locTheta, double& locThetaMin, double& locThetaMax, double& locChiSqPerNDF)
3979{
3980 if(locStereoHits.empty())
3981 return false;
3982 /// Find the theta value using the input stereo hits.
3983 /// The values for dPhiStereo and dStereoHitPos.Z() are assumed to be valid.
3984 /// The value of locFit.r0 is also used to calculate theta.
3985 ///
3986 /// This uses a histogramming technique that looks at the overlaps of the
3987 /// angle ranges subtended by each hit between the given target limits.
3988 /// The overlaps usually lead to a range of values for theta. The limits
3989 /// of these are stored in locThetaMin and locThetaMax.
3990 /// The centroid of the range is stored in the theta field.
3991
3992 // We use a simple array to store our histogram here. We don't want to use
3993 // ROOT histograms because they are not thread safe.
3994 unsigned int Nbins = 1000;
3995 unsigned int hist[Nbins];
3996 for(unsigned int i=0; i<Nbins; ++i)
3997 hist[i] = 0; // clear histogram
3998 double bin_width = M_TWO_PI6.28318530717958647692/(double)Nbins;
3999 double hist_low_limit = -M_PI3.14159265358979323846; // lower edge of histogram limits
4000
4001 // Loop over CDC hits, filling the histogram
4002 double r0 = locFit->r0;
4003 for(unsigned int i=0; i < locStereoHits.size(); ++i)
4004 {
4005 DCDCTrkHit *trkhit = locStereoHits[i];
4006
4007 // Calculate upper and lower limits in theta
4008 double alpha = r0*trkhit->dPhiStereo;
4009 if(locFit->h < 0.0)
4010 alpha = -alpha;
4011 double tmin = atan2(alpha, trkhit->dStereoHitPos.Z() - VERTEX_Z_MIN);
4012 double tmax = atan2(alpha, trkhit->dStereoHitPos.Z() - VERTEX_Z_MAX);
4013 if(tmin>tmax)
4014 {
4015 double tmp = tmin;
4016 tmin=tmax;
4017 tmax=tmp;
4018 }
4019 if(DEBUG_LEVEL>3)
4020 cout<<" -- phi_stereo="<<trkhit->dPhiStereo<<" z_stereo="<<trkhit->dStereoHitPos.Z()<<" alpha="<<alpha<<endl;
4021 if(DEBUG_LEVEL>3)
4022 cout<<" -- tmin="<<tmin<<" tmax="<<tmax<<endl;
4023
4024 // Find index of bins corresponding to tmin and tmax
4025 unsigned int imin = (unsigned int)floor((tmin-hist_low_limit)/bin_width);
4026 unsigned int imax = (unsigned int)floor((tmax-hist_low_limit)/bin_width);
4027
4028 // If entire range of this hit is outside of the histogram limit
4029 // then discard this hit.
4030 if(imin>=Nbins)
4031 continue;
4032
4033 // Clip limits of bin range to our histogram limits
4034 if(imin>=Nbins)
4035 imin=Nbins-1;
4036 if(imax>=Nbins)
4037 imax=Nbins-1;
4038
4039 // Increment all bins between imin and imax
4040 for(unsigned int j=imin; j<=imax; ++j)
4041 ++hist[j];
4042 }
4043
4044 // Look for the indexes of the plateau
4045 unsigned int istart=0;
4046 unsigned int iend=0;
4047 for(unsigned int i=1; i<Nbins; ++i)
4048 {
4049 if(hist[i]>hist[istart])
4050 {
4051 istart = i;
4052 if(DEBUG_LEVEL>3)
4053 cout<<" -- istart="<<istart<<" (theta="<<hist_low_limit + bin_width*(0.5+(double)istart)<<" , N="<<hist[i]<<")"<<endl;
4054 }
4055 if(hist[i] == hist[istart])
4056 iend = i;
4057 }
4058
4059 // If there are no entries in the histogram, then return false
4060 if(hist[istart] == 0)
4061 return false;
4062
4063 // Calculate theta limits
4064 locThetaMin = hist_low_limit + bin_width*(0.5+(double)istart);
4065 locThetaMax = hist_low_limit + bin_width*(0.5+(double)iend);
4066 locTheta = (locThetaMax + locThetaMin)/2.0;
4067 if(DEBUG_LEVEL>3)
4068 cout<<"istart="<<istart<<" iend="<<iend<<" theta_min="<<locThetaMin<<" theta_max="<<locThetaMax<<endl;
4069 locChiSqPerNDF = 9.9E5; //NEED TO CALCULATE THIS!!!
4070
4071 return true;
4072}
4073
4074//-------
4075// Find_Z
4076//-------
4077bool DTrackCandidate_factory_CDC::Find_Z(const DHelicalFit* locFit, const deque<DCDCTrkHit*>& locStereoHits, double locThetaMin, double locThetaMax, double& locZ)
4078{
4079 if(locStereoHits.empty())
4080 return false;
4081
4082 /// Find the z value of the vertex using the stereo hits.
4083 /// The values for dPhiStereo and dStereoHitPos.Z() are assumed to be valid.
4084 ///
4085 /// This uses a histogramming technique that looks at the overlaps of the
4086 /// z ranges subtended by each hit between the given theta limits.
4087 /// The overlaps usually lead to a range of values for z_vertex.
4088 /// The centroid of the range is returned as locZ.
4089
4090 // We use a simple array to store our histogram here. We don't want to use
4091 // ROOT histograms because they are not thread safe.
4092 unsigned int Nbins = 300;
4093 unsigned int hist[Nbins];
4094 for(unsigned int i=0; i<Nbins; ++i)
4095 hist[i] = 0; // clear histogram
4096 double bin_width = 0.5; // bins are 5mm
4097 double hist_low_limit = 0.0; // lower edge of histogram limits
4098
4099 // Loop over CDC hits, filling the histogram
4100 double r0 = locFit->r0;
4101 double tan_alpha_min = tan(locThetaMin)/r0;
4102 double tan_alpha_max = tan(locThetaMax)/r0;
4103 for(unsigned int i=0; i< locStereoHits.size(); ++i)
4104 {
4105 DCDCTrkHit* trkhit = locStereoHits[i];
4106
4107 // Calculate upper and lower limits in z
4108 double q_sign = locFit->h > 0.0 ? +1.0:-1.0;
4109 double zmin = trkhit->dStereoHitPos.Z() - q_sign*trkhit->dPhiStereo/tan_alpha_min;
4110 double zmax = trkhit->dStereoHitPos.Z() - q_sign*trkhit->dPhiStereo/tan_alpha_max;
4111 if(zmin>zmax)
4112 {
4113 double tmp = zmin;
4114 zmin=zmax;
4115 zmax=tmp;
4116 }
4117 if(DEBUG_LEVEL>3)
4118 cout<<" -- phi_stereo="<<trkhit->dPhiStereo<<" z_stereo="<<trkhit->dStereoHitPos.Z()<<endl;
4119 if(DEBUG_LEVEL>3)
4120 cout<<" -- zmin="<<zmin<<" zmax="<<zmax<<endl;
4121
4122 // Find index of bins corresponding to tmin and tmax
4123 unsigned int imin = (unsigned int)floor((zmin-hist_low_limit)/bin_width);
4124 unsigned int imax = (unsigned int)floor((zmax-hist_low_limit)/bin_width);
4125
4126 // If entire range of this hit is outside of the histogram limit
4127 // then discard this hit.
4128 if(imax<=0 || imin>=Nbins)
4129 continue;
4130
4131 // Clip limits of bin range to our histogram limits
4132 if(imin>=Nbins)
4133 imin=Nbins-1;
4134 if(imax>=Nbins)
4135 imax=Nbins-1;
4136
4137 // Increment all bins between imin and imax
4138 for(unsigned int j=imin; j<=imax; ++j)
4139 ++hist[j];
4140 }
4141
4142 // Look for the indexes of the plateau
4143 unsigned int istart=0;
4144 unsigned int iend=0;
4145 for(unsigned int i=1; i<Nbins; ++i)
4146 {
4147 if(hist[i]>hist[istart])
4148 {
4149 istart = i;
4150 if(DEBUG_LEVEL>3)
4151 cout<<" -- istart="<<istart<<" (z="<<hist_low_limit + bin_width*(0.5+(double)istart)<<" , N="<<hist[i]<<")"<<endl;
4152 }
4153 if(hist[i] == hist[istart])
4154 iend = i;
4155 }
4156
4157 // If there are no entries in the histogram, then return false
4158 if(hist[istart] == 0)
4159 return false;
4160
4161 // Calculate z limits
4162 double locZMin = hist_low_limit + bin_width*(0.5+(double)istart);
4163 double locZMax = hist_low_limit + bin_width*(0.5+(double)iend);
4164 locZ = (locZMax + locZMin)/2.0;
4165 if(DEBUG_LEVEL>3)
4166 cout<<"istart="<<istart<<" iend="<<iend<<" z_min="<<locZMin<<" z_max="<<locZMax<<" hits[istart]="<<hist[istart]<<endl;
4167 return true;
4168}
4169
4170//---------------------------
4171// Recycle_DCDCSuperLayerSeed
4172//---------------------------
4173void DTrackCandidate_factory_CDC::Recycle_DCDCSuperLayerSeed(DCDCSuperLayerSeed* locCDCSuperLayerSeed)
4174{
4175 // this function should ONLY be called for stereo super layers AFTER the hits have been projected onto the circle (new hit objects were made)
4176 // this is useful for recycling the memory used by the projected hits and seeds
4177 // first loop over the hits: see if can recycle those as well (each hit can be used in multiple seeds)
4178
4179 deque<DCDCTrkHit*> locHits;
4180 locCDCSuperLayerSeed->Get_Hits(locHits);
4181 for(size_t loc_i = 0; loc_i < locHits.size(); ++loc_i)
4182 {
4183 DCDCTrkHit* locCDCTrkHit = locHits[loc_i];
4184 if(dStereoHitNumUsedMap[locCDCTrkHit] == 1) //this is the last remaining DCDCSuperLayerSeed this hit is used in: recycle it
4185 dCDCTrkHitPool_Available.push_back(locCDCTrkHit);
4186 else
4187 --dStereoHitNumUsedMap[locCDCTrkHit];
4188 }
4189 dCDCSuperLayerSeedPool_Available.push_back(locCDCSuperLayerSeed); //recycle
4190}
4191
4192//---------------------------
4193// Recycle_DCDCTrackCircle
4194//---------------------------
4195void DTrackCandidate_factory_CDC::Recycle_DCDCTrackCircle(DCDCTrackCircle* locCDCTrackCircle)
4196{
4197 if(locCDCTrackCircle->fit != NULL__null)
4198 {
4199 dHelicalFitPool_Available.push_back(locCDCTrackCircle->fit);
4200 locCDCTrackCircle->fit = NULL__null;
4201 }
4202 locCDCTrackCircle->Reset();
4203 dCDCTrackCirclePool_Available.push_back(locCDCTrackCircle); //recycle
4204}
4205
4206//----------------------
4207// Set_HitBitPattern_All
4208//----------------------
4209void DTrackCandidate_factory_CDC::Set_HitBitPattern_All(deque<DCDCTrackCircle*>& locCDCTrackCircles)
4210{
4211 unsigned int locNumBits = 8*sizeof(unsigned int);
4212 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
4213 {
4214 DCDCTrackCircle* locCDCTrackCircle = locCDCTrackCircles[loc_i];
4215 locCDCTrackCircle->HitBitPattern.clear();
4216 locCDCTrackCircle->HitBitPattern.resize(dNumCDCHits/(8*sizeof(unsigned int)) + 1);
4217 deque<DCDCTrkHit*> locHits;
4218 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_j)
4219 {
4220 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_j]->Get_Hits(locHits);
4221 for(size_t loc_k = 0; loc_k < locHits.size(); ++loc_k)
4222 locCDCTrackCircle->HitBitPattern[locHits[loc_k]->index/locNumBits] |= 1 << locHits[loc_k]->index % locNumBits;
4223 }
4224
4225 if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
4226 {
4227 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0].size(); ++loc_j)
4228 {
4229 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0][loc_j]->Get_Hits(locHits);
4230 for(size_t loc_k = 0; loc_k < locHits.size(); ++loc_k)
4231 locCDCTrackCircle->HitBitPattern[locHits[loc_k]->index/locNumBits] |= 1 << locHits[loc_k]->index % locNumBits;
4232 }
4233 }
4234 if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
4235 {
4236 for(size_t loc_j = 0; loc_j < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0].size(); ++loc_j)
4237 {
4238 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0][loc_j]->Get_Hits(locHits);
4239 for(size_t loc_k = 0; loc_k < locHits.size(); ++loc_k)
4240 locCDCTrackCircle->HitBitPattern[locHits[loc_k]->index/locNumBits] |= 1 << locHits[loc_k]->index % locNumBits;
4241 }
4242 }
4243 }
4244}
4245
4246//---------------------------
4247// Filter_TrackCircles_Stereo
4248//---------------------------
4249void DTrackCandidate_factory_CDC::Filter_TrackCircles_Stereo(deque<DCDCTrackCircle*>& locCDCTrackCircles)
4250{
4251 if(locCDCTrackCircles.empty())
4252 return;
4253
4254 //sort track circles so that the ones with the best stereo chisq/ndf are first
4255 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByStereoChiSqPerNDFIncreasing);
4256
4257 if(DEBUG_LEVEL > 5)
4258 {
4259 cout << "filter stereo, circles sorted by stereo chisq/ndf" << endl;
4260 Print_TrackCircles(locCDCTrackCircles);
4261 }
4262
4263 //FIRST: Delete super layer seeds if they are shared between circles: delete it from the one with the worst dWeightedChiSqPerDF_Stereo
4264 // 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
4265 // However, DO NOT delete the super layer seed if it is the last one on the track
4266 for(size_t loc_i = 0; loc_i < (locCDCTrackCircles.size() - 1); ++loc_i)
4267 {
4268 //assume this track circle has no wrong seeds (since it has the best chisq/ndf of all circles containing any of these seeds)
4269 DCDCTrackCircle* locTrackCircle_ToCompareTo = locCDCTrackCircles[loc_i];
4270 deque<DCDCSuperLayerSeed*> locStereoSuperLayerSeeds;
4271 locTrackCircle_ToCompareTo->Get_AllStereoSuperLayerSeeds(locStereoSuperLayerSeeds);
4272 //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
4273 //should recycle...
4274 bool locSeedsStrippedFlag_AnyCircle = false;
4275 for(size_t loc_j = loc_i + 1; loc_j < locCDCTrackCircles.size(); ++loc_j)
4276 {
4277 DCDCTrackCircle* locTrackCircle_Validating = locCDCTrackCircles[loc_j];
4278 if(locTrackCircle_Validating->Get_NumStereoSuperLayerSeeds() <= 1)
4279 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)
4280 bool locSeedsStrippedFlag = false;
4281 for(size_t loc_k = 0; loc_k < locStereoSuperLayerSeeds.size(); ++loc_k)
4282 {
4283 if(locTrackCircle_Validating->Get_NumStereoSuperLayerSeeds() <= 1)
4284 break;
4285 //remember, can't compare pointers directly (made new objects for projection to track circle), must compare dSuperLayer and dSeedIndex
4286 unsigned int locSuperLayer = locStereoSuperLayerSeeds[loc_k]->dSuperLayer;
4287 unsigned int locSeedIndex = locStereoSuperLayerSeeds[loc_k]->dSeedIndex;
4288 DCDCSuperLayerSeed* locSuperLayerSeed = locTrackCircle_Validating->Get_SuperLayerSeed(locSuperLayer);
4289 if(locSuperLayerSeed == NULL__null)
4290 continue;
4291 if((locSuperLayerSeed->dSuperLayer != locSuperLayer) || (locSuperLayerSeed->dSeedIndex != locSeedIndex))
4292 continue;
4293 //stereo super layer is shared by both track circles, reject it from the one with the worse stereo chisq/ndf (weighted)
4294 if(DEBUG_LEVEL > 10)
4295 cout << "strip SL" << locSuperLayer << " from track circle " << loc_j << endl;
4296 locTrackCircle_Validating->Strip_StereoSuperLayerSeed(locSuperLayer);
4297 locSeedsStrippedFlag = true; //may want to recalc theta/z
4298 locSeedsStrippedFlag_AnyCircle = true;
4299 }
4300 if(locSeedsStrippedFlag) //recalc theta/z to get new chisq/ndf
4301 Select_CDCSuperLayerSeeds(locTrackCircle_Validating, false);
4302 }
4303
4304 if(locSeedsStrippedFlag_AnyCircle) //re-sort if fits have been re-performed
4305 sort(locCDCTrackCircles.begin() + loc_i + 1, locCDCTrackCircles.end(), CDCSortByStereoChiSqPerNDFIncreasing);
4306 }
4307
4308 //restore sort by circle-fit chisq/ndf (weighted)
4309 sort(locCDCTrackCircles.begin(), locCDCTrackCircles.end(), CDCSortByChiSqPerNDFDecreasing);
4310
4311 if(DEBUG_LEVEL > 5)
4312 {
4313 cout << "filter stereo, circles sorted by axial chisq/ndf" << endl;
4314 Print_TrackCircles(locCDCTrackCircles);
4315 }
4316}
4317
4318//---------------
4319// Add_UnusedHits
4320//---------------
4321void DTrackCandidate_factory_CDC::Add_UnusedHits(deque<DCDCTrackCircle*>& locCDCTrackCircles)
4322{
4323 if(DEBUG_LEVEL > 5)
4324 cout << "Add unused hits" << endl;
4325
4326 // 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
4327 // Only add them if they can link to the previous super layer, and wouldn't skip too many rings
4328 // Add at most one hit: prefer the hit on the innermost ring
4329 //If more than one hit on the innermost axial ring: choose the one closest to the circle fit
4330 //If more than one hit on the innermost stereo ring: ambiguous, don't add any hits
4331 for(size_t loc_i = 0; loc_i < locCDCTrackCircles.size(); ++loc_i)
4332 {
4333 DCDCSuperLayerSeed* locLastSuperLayerSeed = locCDCTrackCircles[loc_i]->Get_LastSuperLayerSeed();
4334 unsigned int locLastSuperLayer = locLastSuperLayerSeed->dSuperLayer;
4335 if(DEBUG_LEVEL > 5)
4336 cout << "i, last super layer = " << loc_i << ", " << locLastSuperLayer << endl;
4337 if(locLastSuperLayer == 7)
4338 continue;
4339 unsigned int locSearchSuperLayer = locLastSuperLayer + 1;
4340 const DHelicalFit* locFit = locCDCTrackCircles[loc_i]->fit;
4341
4342 //make sure the next super layer doesn't correspond to a region where all of the seeds were deleted earlier (density too high)
4343 double locSeedFirstPhi, locSeedLastPhi;
4344 Calc_SuperLayerPhiRange(locLastSuperLayerSeed, locSeedFirstPhi, locSeedLastPhi);
4345 bool locHitDensityTooHighFlag = false;
4346 for(size_t loc_k = 0; loc_k < dRejectedPhiRegions[locSearchSuperLayer].size(); ++loc_k)
4347 {
4348 if(!Check_IfPhiRangesOverlap(locSeedFirstPhi, locSeedLastPhi, dRejectedPhiRegions[locSearchSuperLayer][loc_k].first, dRejectedPhiRegions[locSearchSuperLayer][loc_k].second))
4349 continue;
4350 locHitDensityTooHighFlag = true;
4351 break;
4352 }
4353 if(locHitDensityTooHighFlag)
4354 {
4355 if(DEBUG_LEVEL > 5)
4356 cout << "hit density too high, don't add unused hits" << endl;
4357 continue; //hit density in this region is too high, ignore all hits here
4358 }
4359
4360 //make sure we don't skip too many rings
4361 int locLastHitRing = locLastSuperLayerSeed->dCDCRingSeeds.back().ring;
4362 if((4*locLastSuperLayer - locLastHitRing) > MAX_NUM_RINGSEED_RINGS_SKIPABLE)
4363 {
4364 if(DEBUG_LEVEL > 5)
4365 cout << "too many rings missing at the end of the last super layer: actual, max = " << 4*locLastSuperLayer - locLastHitRing << ", " << MAX_NUM_RINGSEED_RINGS_SKIPABLE << endl;
4366 continue; //too many rings missing at the end of the last super layer
4367 }
4368
4369 wire_direction_t locWireDirection;
4370 if((locSearchSuperLayer == 1) || (locSearchSuperLayer == 4) || (locSearchSuperLayer == 7))
4371 locWireDirection = WIRE_DIRECTION_AXIAL;
4372 else if((locSearchSuperLayer == 2) || (locSearchSuperLayer == 6))
4373 locWireDirection = WIRE_DIRECTION_STEREOLEFT;
4374 else
4375 locWireDirection = WIRE_DIRECTION_STEREORIGHT;
4376
4377 //ok, look for unused hits within a certain angle/distance from the circle fit
4378 DCDCTrkHit* locBestTrkHit = NULL__null;
4379 int locAmbiguousHitRing = -1; //if != -1, ignore all hits in or above this ring //set if > 1 stereo hit that matches on this ring
4380 double locBestDeltaPhi = 9.9E9; //for axial if > 1 hit on innermost ring
4381 for(size_t loc_j = 0; loc_j < cdchits_by_superlayer[locSearchSuperLayer - 1].size(); ++loc_j)
4382 {
4383 DCDCTrkHit* locTrkHit = cdchits_by_superlayer[locSearchSuperLayer - 1][loc_j];
4384 if(locTrkHit->flags & USED)
4385 continue; //not a lone hit: used in a super layer seed
4386 if(locTrkHit->hit->wire->ring == locAmbiguousHitRing)
4387 continue; // already > 1 stereo hit on this ring: ambiguous as to which hit is best
4388
4389 //make sure we don't skip too many rings
4390 int locNumRingsSkipped = locTrkHit->hit->wire->ring - locLastHitRing - 1;
4391 if(locNumRingsSkipped > int(MAX_NUM_RINGSEED_RINGS_SKIPABLE))
4392 {
4393 if(DEBUG_LEVEL > 5)
4394 cout << "would skip too many rings: actual, max = " << locNumRingsSkipped << ", " << MAX_NUM_RINGSEED_RINGS_SKIPABLE << endl;
4395 continue; //would skip too many rings
4396 }
4397
4398 // see if the hit has small-enough transverse distance to the previous super layer
4399 DCDCRingSeed locRingSeed;
4400 locRingSeed.hits.push_back(locTrkHit);
4401 locRingSeed.ring = locTrkHit->hit->wire->ring;
4402 locRingSeed.linked = false;
4403 if(!Attempt_SeedLink(locLastSuperLayerSeed->dCDCRingSeeds.back(), locRingSeed, locLastSuperLayerSeed->dWireOrientation, locWireDirection))
4404 {
4405 if(DEBUG_LEVEL > 5)
4406 cout << "new hit isn't close to wires in previous seed" << endl;
4407 continue; //new hit isn't close to wires in previous seed
4408 }
4409 if(DEBUG_LEVEL > 5)
4410 cout << "hit is close to wires in previous seed, ring = " << locTrkHit->hit->wire->ring << endl;
4411
4412 // If axial, require that the hit be near the circle fit.
4413 double locDeltaPhi = 9.9E9;
4414 if((locSearchSuperLayer == 4) || (locSearchSuperLayer == 7))
4415 {
4416 // Find the position on the circle that is closest to locTrkHit
4417 const DVector3 locOrigin = locTrkHit->hit->wire->origin;
4418 double dx = locOrigin.x() - locFit->x0;
4419 double dy = locOrigin.y() - locFit->y0;
4420 double one_over_denom = 1.0/sqrt(dx*dx + dy*dy);
4421 double x = locFit->x0 + locFit->r0*dx*one_over_denom;
4422 double y = locFit->y0 + locFit->r0*dy*one_over_denom;
4423 DVector2 locCirclePosition(x, y);
4424
4425 // Compare phi values to see if the seeds are close enough to link
4426 locDeltaPhi = fabs(locCirclePosition.Phi() - locOrigin.Phi());
4427 while(locDeltaPhi > M_PI3.14159265358979323846)
4428 locDeltaPhi -= M_TWO_PI6.28318530717958647692;
4429 locDeltaPhi *= 180.0/M_PI3.14159265358979323846;
4430 if(DEBUG_LEVEL > 5)
4431 cout << "hit is axial, check if delta phi is close enough: " << fabs(locDeltaPhi) << ", " << MAX_UNUSED_HIT_LINK_ANGLE << endl;
4432 if(fabs(locDeltaPhi) > MAX_UNUSED_HIT_LINK_ANGLE)
4433 continue; //hit is too far away from the current circle fit
4434 }
4435
4436 //Have a matching unused hit. Now make sure it is the best one so far.
4437
4438 if(locBestTrkHit == NULL__null)
4439 {
4440 //No best hit before, save this result
4441 locBestTrkHit = locTrkHit;
4442 locBestDeltaPhi = locDeltaPhi;
4443 if(DEBUG_LEVEL > 5)
4444 cout << "brand new track hit, delta phi = " << locBestDeltaPhi << endl;
4445 continue;
4446 }
4447
4448 if(locTrkHit->hit->wire->ring > locBestTrkHit->hit->wire->ring)
4449 {
4450 //ring is larger: new hit not as good as the current best one
4451 if(DEBUG_LEVEL > 5)
4452 cout << "new hit not as good as the current best one" << endl;
4453 continue;
4454 }
4455
4456 if(locTrkHit->hit->wire->ring < locBestTrkHit->hit->wire->ring)
4457 {
4458 //ring is smaller: new hit better than the one we had before
4459 locAmbiguousHitRing = -1;
4460 locBestTrkHit = locTrkHit;
4461 locBestDeltaPhi = locDeltaPhi;
4462 if(DEBUG_LEVEL > 5)
4463 cout << "new best track hit (better ring), delta phi = " << locBestDeltaPhi << endl;
4464 continue;
4465 }
4466
4467 //The new hit is on the same ring as the previous best hit.
4468
4469 if((locSearchSuperLayer != 4) && (locSearchSuperLayer != 7))
4470 {
4471 //stereo: can't tell which hit is best, label ring as ambiguous
4472 locAmbiguousHitRing = locBestTrkHit->hit->wire->ring;
4473 locBestTrkHit = NULL__null;
4474 if(DEBUG_LEVEL > 5)
4475 cout << "stereo, can't tell which hit is best, label ring " << locAmbiguousHitRing << " as ambiguous" << endl;
4476 continue;
4477 }
4478
4479 //Axial, see if closest to the track circle (smallest delta phi)
4480 if(locDeltaPhi >= locBestDeltaPhi)
4481 {
4482 //delta-phi is larger: new hit not as good as the current best one
4483 if(DEBUG_LEVEL > 5)
4484 cout << "axial, not the best hit, phis = " << locDeltaPhi << ", " << locBestDeltaPhi << endl;
4485 continue;
4486 }
4487
4488 //delta-phi is smaller: new hit better than the current best one: save it
4489 locBestTrkHit = locTrkHit;
4490 locBestDeltaPhi = locDeltaPhi;
4491 if(DEBUG_LEVEL > 5)
4492 cout << "new best track hit (same ring), delta phi = " << locBestDeltaPhi << endl;
4493 }
4494 if(locBestTrkHit == NULL__null)
4495 continue; // no hit found for this track (or hits were ambiguous)
4496
4497 // add best hit to track: create new DCDCSuperLayerSeed for it, add to circle fit
4498 locBestTrkHit->flags |= USED;
4499 DCDCRingSeed locRingSeed;
4500 locRingSeed.hits.push_back(locBestTrkHit);
4501 locRingSeed.ring = locBestTrkHit->hit->wire->ring;
4502 locRingSeed.linked = true;
4503
4504 DCDCSuperLayerSeed* locNewSuperLayerSeed = Get_Resource_CDCSuperLayerSeed();
4505 locNewSuperLayerSeed->dCDCRingSeeds.push_back(locRingSeed);
4506 locNewSuperLayerSeed->dSuperLayer = locSearchSuperLayer;
4507 locNewSuperLayerSeed->dSeedIndex = dSuperLayerSeeds[locSearchSuperLayer - 1].size();
4508 locNewSuperLayerSeed->linked = true;
4509 locNewSuperLayerSeed->dWireOrientation = locWireDirection;
4510 dSuperLayerSeeds[locSearchSuperLayer - 1].push_back(locNewSuperLayerSeed);
4511 locCDCTrackCircles[loc_i]->Add_LastSuperLayerSeed(locNewSuperLayerSeed);
4512 }
4513}
4514
4515//-----------------------
4516// Create_TrackCandidiate
4517//-----------------------
4518void DTrackCandidate_factory_CDC::Create_TrackCandidiate(DCDCTrackCircle* locCDCTrackCircle)
4519{
4520 DVector3 pos, mom;
4521 if(!Calc_PositionAndMomentum(locCDCTrackCircle, pos, mom))
4522 {
4523 if(DEBUG_LEVEL > 5)
4524 cout << "Track momentum not greater than zero (or NaN), DTrackCandidate object not created." << endl;
4525 return; //don't create object!!
4526 }
4527
4528 DTrackCandidate *locTrackCandidate = new DTrackCandidate;
4529 locTrackCandidate->setCharge(locCDCTrackCircle->fit->h*dFactorForSenseOfRotation);
4530
4531 locTrackCandidate->chisq = locCDCTrackCircle->fit->chisq;
4532 locTrackCandidate->Ndof = locCDCTrackCircle->fit->ndof;
4533 locTrackCandidate->setPosition(pos);
4534 locTrackCandidate->setMomentum(mom);
4535
4536 // Add axial hits (if any)
4537 deque<DCDCTrkHit*> locHits;
4538 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_i)
4539 {
4540 locCDCTrackCircle->dSuperLayerSeeds_Axial[loc_i]->Get_Hits(locHits);
4541 for(size_t loc_j = 0; loc_j < locHits.size(); ++loc_j)
4542 {
4543 locTrackCandidate->AddAssociatedObject(locHits[loc_j]->hit);
4544 locTrackCandidate->used_cdc_indexes.push_back(locHits[loc_j]->index);
4545 }
4546 }
4547
4548 // Add inner stereo hits (if any)
4549 if(!locCDCTrackCircle->dSuperLayerSeeds_InnerStereo.empty())
4550 {
4551 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0].size(); ++loc_i) //only one seed series: the "best" one
4552 {
4553 locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0][loc_i]->Get_Hits(locHits);
4554 for(size_t loc_j = 0; loc_j < locHits.size(); ++loc_j)
4555 {
4556 locTrackCandidate->AddAssociatedObject(locHits[loc_j]->hit);
4557 locTrackCandidate->used_cdc_indexes.push_back(locHits[loc_j]->index);
4558 }
4559 }
4560 }
4561
4562 // Add outer stereo hits (if any)
4563 if(!locCDCTrackCircle->dSuperLayerSeeds_OuterStereo.empty())
4564 {
4565 for(size_t loc_i = 0; loc_i < locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0].size(); ++loc_i) //only one seed series: the "best" one
4566 {
4567 locCDCTrackCircle->dSuperLayerSeeds_OuterStereo[0][loc_i]->Get_Hits(locHits);
4568 for(size_t loc_j = 0; loc_j < locHits.size(); ++loc_j)
4569 {
4570 locTrackCandidate->AddAssociatedObject(locHits[loc_j]->hit);
4571 locTrackCandidate->used_cdc_indexes.push_back(locHits[loc_j]->index);
4572 }
4573 }
4574 }
4575
4576 if(DEBUG_LEVEL>3)
4577 cout<<"Final Candidate parameters: p="<<mom.Mag()<<" theta="<<mom.Theta()<<" phi="<<mom.Phi()<<" z="<<pos.Z()<<endl;
4578
4579 _data.push_back(locTrackCandidate);
4580}
4581
4582//-------------------------
4583// Calc_PositionAndMomentum
4584//-------------------------
4585bool DTrackCandidate_factory_CDC::Calc_PositionAndMomentum(DCDCTrackCircle* locCDCTrackCircle, DVector3 &pos, DVector3 &mom)
4586{
4587 // Get the position and momentum at a fixed radius from the beam line
4588
4589 // Direction tangent
4590 double tanl = tan(M_PI_21.57079632679489661923 - locCDCTrackCircle->dTheta);
4591
4592 // Squared radius of cylinder outside start counter but inside CDC inner
4593 // radius
4594 double r2 = 90.0;
4595
4596 // Circle parameters
4597 double xc = locCDCTrackCircle->fit->x0;
4598 double yc = locCDCTrackCircle->fit->y0;
4599 double rc = locCDCTrackCircle->fit->r0;
4600 double rc2 = rc*rc;
4601 double xc2 = xc*xc;
4602 double yc2 = yc*yc;
4603 double xc2_plus_yc2 = xc2 + yc2;
4604
4605 // variables needed for intersection of circles
4606 double a = (r2 - xc2_plus_yc2 - rc2)/(2.*rc);
4607 double temp1 = yc*sqrt(xc2_plus_yc2 - a*a);
4608 double temp2 = xc*a;
4609 double cosphi_plus = (temp2 + temp1)/xc2_plus_yc2;
4610 double cosphi_minus = (temp2 - temp1)/xc2_plus_yc2;
4611
4612 // Check for intersections
4613 if(!isfinite(temp1) || !isfinite(temp2))
4614 {
4615 // We did not find an intersection between the two circles, so return
4616 // sensible defaults for pos and mom
4617 double my_seed_phi = locCDCTrackCircle->fit->phi;
4618 double my_center_phi = atan2(yc,xc);
4619 double xv = xc - rc*cos(my_center_phi);
4620 double yv = yc - rc*sin(my_center_phi);
4621 pos.SetXYZ(xv, yv, locCDCTrackCircle->dVertexZ);
4622
4623 double pt = 0.003*fabs(dMagneticField->GetBz(pos.x(), pos.y(), pos.z()))*rc;
4624 mom.SetXYZ(pt*cos(my_seed_phi), pt*sin(my_seed_phi), pt*tanl);
4625 return (mom.Mag() > 0.0);
4626 }
4627
4628 // if we have intersections, find both solutions
4629 double phi_plus = -acos(cosphi_plus);
4630 double phi_minus = -acos(cosphi_minus);
4631 double x_plus = xc + rc*cosphi_plus;
4632 double x_minus = xc + rc*cosphi_minus;
4633 double y_plus = yc + rc*sin(phi_plus);
4634 double y_minus = yc + rc*sin(phi_minus);
4635
4636 // if the resulting radial position on the circle from the fit does not agree
4637 // with the radius to which we are matching, we have the wrong sign for phi+
4638 // or phi-
4639 double r2_plus = x_plus*x_plus + y_plus*y_plus;
4640 double r2_minus = x_minus*x_minus + y_minus*y_minus;
4641 if(fabs(r2 - r2_plus) > EPS1e-3)
4642 {
4643 phi_plus *= -1.;
4644 y_plus = yc + rc*sin(phi_plus);
4645 }
4646 if(fabs(r2 - r2_minus) > EPS1e-3)
4647 {
4648 phi_minus *= -1.;
4649 y_minus = yc + rc*sin(phi_minus);
4650 }
4651
4652 // Choose phi- or phi+ depending on proximity to one of the cdc hits
4653 DCDCTrkHit* locFirstHit = NULL__null;
4654 if(locCDCTrackCircle->dSuperLayerSeeds_Axial.empty())
4655 locFirstHit = locCDCTrackCircle->dSuperLayerSeeds_InnerStereo[0][0]->dCDCRingSeeds[0].hits[0];
4656 else
4657 locFirstHit = locCDCTrackCircle->dSuperLayerSeeds_Axial[0]->dCDCRingSeeds[0].hits[0];
4658
4659 double xwire = locFirstHit->hit->wire->origin.x();
4660 double ywire = locFirstHit->hit->wire->origin.y();
4661 double dx = x_minus - xwire;
4662 double dy = y_minus - ywire;
4663 double d2_minus = dx*dx + dy*dy;
4664 dx = x_plus - xwire;
4665 dy = y_plus - ywire;
4666 double d2_plus = dx*dx + dy*dy;
4667 if(d2_plus > d2_minus)
4668 {
4669 phi_minus *= -1.;
4670 if(locCDCTrackCircle->fit->h < 0)
4671 phi_minus += M_PI3.14159265358979323846;
4672 double myphi = atan2(yc, xc);
4673 double xv = xc - rc*cos(myphi);
4674 double yv = yc - rc*sin(myphi);
4675 double dx = x_minus - xv;
4676 double dy = y_minus - yv;
4677 double chord = sqrt(dx*dx + dy*dy);
4678 double two_rc = 2.*rc;
4679 double ratio = chord/two_rc;
4680 double ds = (ratio < 1.) ? (two_rc*asin(ratio)) : (two_rc*M_PI_21.57079632679489661923);
4681 pos.SetXYZ(x_minus, y_minus, locCDCTrackCircle->dVertexZ + ds*tanl);
4682
4683 double pt = 0.003*fabs(dMagneticField->GetBz(pos.x(), pos.y(), pos.z()))*rc;
4684 mom.SetXYZ(pt*sin(phi_minus), pt*cos(phi_minus), pt*tanl);
4685 }
4686 else
4687 {
4688 phi_plus *= -1.;
4689 if(locCDCTrackCircle->fit->h < 0)
4690 phi_plus += M_PI3.14159265358979323846;
4691 double myphi = atan2(yc, xc);
4692 double xv = xc - rc*cos(myphi);
4693 double yv = yc - rc*sin(myphi);
4694 double dx = x_plus - xv;
4695 double dy = y_plus - yv;
4696 double chord = sqrt(dx*dx + dy*dy);
4697 double two_rc = 2.*rc;
4698 double ratio = chord/two_rc;
4699 double ds = (ratio < 1.) ? (two_rc*asin(ratio)) : (two_rc*M_PI_21.57079632679489661923);
4700 pos.SetXYZ(x_plus, y_plus, locCDCTrackCircle->dVertexZ + ds*tanl);
4701
4702 double pt =0.003*fabs(dMagneticField->GetBz(pos.x(), pos.y(), pos.z()))*rc;
4703 mom.SetXYZ(pt*sin(phi_plus), pt*cos(phi_plus), pt*tanl);
4704 }
4705 return (mom.Mag() > 0.0);
4706}
4707
4708//------------------
4709// erun
4710//------------------
4711jerror_t DTrackCandidate_factory_CDC::erun(void)
4712{
4713 return NOERROR;
4714}
4715
4716//------------------
4717// fini
4718//------------------
4719jerror_t DTrackCandidate_factory_CDC::fini(void)
4720{
4721 // Delete memory in resource pools
4722 for(size_t loc_i = 0; loc_i < dCDCTrkHitPool_All.size(); ++loc_i)
4723 delete dCDCTrkHitPool_All[loc_i];
4724
4725 for(size_t loc_i = 0; loc_i < dCDCSuperLayerSeedPool_All.size(); ++loc_i)
4726 delete dCDCSuperLayerSeedPool_All[loc_i];
4727
4728 for(size_t loc_i = 0; loc_i < dHelicalFitPool_All.size(); ++loc_i)
4729 delete dHelicalFitPool_All[loc_i];
4730
4731 for(size_t loc_i = 0; loc_i < dCDCTrackCirclePool_All.size(); ++loc_i)
4732 delete dCDCTrackCirclePool_All[loc_i];
4733
4734 return NOERROR;
4735}
4736
4737void DTrackCandidate_factory_CDC::DCDCTrkHit::Reset(void)
4738{
4739 hit = NULL__null;
4740 index = 0;
4741 flags = NONE;
4742 var_z = 0.0;
4743 dStereoHitPos.SetXYZ(0.0, 0.0, 0.0);
4744 dPhiStereo = 0.0;
4745 dValidStereoHitPosFlag = false;
4746}
4747
4748void DTrackCandidate_factory_CDC::DCDCSuperLayerSeed::Reset(void)
4749{
4750 dSuperLayer = 0;
4751 dSeedIndex = 0;
4752 linked = false;
4753 dSpiralLinkParams.clear();
4754 dCDCRingSeeds.clear();
4755}
4756
4757bool DTrackCandidate_factory_CDC::DCDCSuperLayerSeed::Are_AllHitsOnRingShared(const DCDCSuperLayerSeed* locCDCSuperLayerSeed, int locRing) const
4758{
4759 deque<DCDCTrkHit*> locRingHits;
4760 for(size_t loc_i = 0; loc_i < dCDCRingSeeds.size(); ++loc_i)
4761 {
4762 if(dCDCRingSeeds[loc_i].ring != locRing)
4763 continue;
4764 locRingHits = dCDCRingSeeds[loc_i].hits;
4765 break;
4766 }
4767
4768 deque<DCDCTrkHit*> locRingHits_CompareTo;
4769 for(size_t loc_i = 0; loc_i < locCDCSuperLayerSeed->dCDCRingSeeds.size(); ++loc_i)
4770 {
4771 if(locCDCSuperLayerSeed->dCDCRingSeeds[loc_i].ring != locRing)
4772 continue;
4773 locRingHits_CompareTo = locCDCSuperLayerSeed->dCDCRingSeeds[loc_i].hits;
4774 break;
4775 }
4776
4777 return (locRingHits == locRingHits_CompareTo);
4778}
4779
4780void DTrackCandidate_factory_CDC::DCDCTrackCircle::Reset(void)
4781{
4782 dSuperLayerSeeds_Axial.clear();
4783 dSuperLayerSeeds_InnerStereo.clear();
4784 dSuperLayerSeeds_OuterStereo.clear();
4785 fit = NULL__null;
4786 dWeightedChiSqPerDF = 0.0;
4787 dAverageDriftTime = 0.0;
4788 HitBitPattern.clear();
4789 dTheta = 0.0;
4790 dVertexZ = 0.0;
4791 dSpiralTurnRing = -1;
4792 dTruncationSourceCircles.clear();
4793 dHasNonTruncatedSeedsFlag_InnerStereo = false;
4794 dHasNonTruncatedSeedsFlag_OuterStereo = false;
4795 dWeightedChiSqPerDF_Stereo = 0.0;
4796}
4797
4798DTrackCandidate_factory_CDC::DCDCSuperLayerSeed* DTrackCandidate_factory_CDC::DCDCTrackCircle::Get_LastSuperLayerSeed(void) const
4799{
4800 //only checks the first combination of stereo seeds
4801 DCDCSuperLayerSeed* locLastAxialSuperLayerSeed = NULL__null;
4802 if(!dSuperLayerSeeds_Axial.empty())
4803 {
4804 locLastAxialSuperLayerSeed = dSuperLayerSeeds_Axial.back();
4805 if(locLastAxialSuperLayerSeed->dSuperLayer == 7)
4806 return locLastAxialSuperLayerSeed;
4807 }
4808 else if(!dSuperLayerSeeds_OuterStereo.empty())
4809 {
4810 if(dSuperLayerSeeds_OuterStereo[0].back()->dSuperLayer > locLastAxialSuperLayerSeed->dSuperLayer)
4811 return dSuperLayerSeeds_OuterStereo[0].back();
4812 }
4813 else if(!dSuperLayerSeeds_InnerStereo.empty())
4814 {
4815 if(dSuperLayerSeeds_InnerStereo[0].back()->dSuperLayer > locLastAxialSuperLayerSeed->dSuperLayer)
4816 return dSuperLayerSeeds_InnerStereo[0].back();
4817 }
4818 return locLastAxialSuperLayerSeed;
4819}
4820
4821DTrackCandidate_factory_CDC::DCDCSuperLayerSeed* DTrackCandidate_factory_CDC::DCDCTrackCircle::Get_SuperLayerSeed(unsigned int locSuperLayer) const
4822{
4823 //only checks the first combination of stereo seeds
4824 if((locSuperLayer == 1) || (locSuperLayer == 4) || (locSuperLayer == 7))
4825 {
4826 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_Axial.size(); ++loc_i)
4827 {
4828 if(dSuperLayerSeeds_Axial[loc_i]->dSuperLayer == locSuperLayer)
4829 return dSuperLayerSeeds_Axial[loc_i];
4830 }
4831 return NULL__null;
4832 }
4833 else if((locSuperLayer == 2) || (locSuperLayer == 3))
4834 {
4835 if(dSuperLayerSeeds_InnerStereo.empty())
4836 return NULL__null;
4837 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_InnerStereo[0].size(); ++loc_i)
4838 {
4839 if(dSuperLayerSeeds_InnerStereo[0][loc_i]->dSuperLayer == locSuperLayer)
4840 return dSuperLayerSeeds_InnerStereo[0][loc_i];
4841 }
4842 }
4843 else //outer SL seeds could be listed as inner (e.g. no SL4)
4844 {
4845 if(!dSuperLayerSeeds_OuterStereo.empty())
4846 {
4847 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_OuterStereo[0].size(); ++loc_i)
4848 {
4849 if(dSuperLayerSeeds_OuterStereo[0][loc_i]->dSuperLayer == locSuperLayer)
4850 return dSuperLayerSeeds_OuterStereo[0][loc_i];
4851 }
4852 }
4853 if(!dSuperLayerSeeds_InnerStereo.empty())
4854 {
4855 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_InnerStereo[0].size(); ++loc_i)
4856 {
4857 if(dSuperLayerSeeds_InnerStereo[0][loc_i]->dSuperLayer == locSuperLayer)
4858 return dSuperLayerSeeds_InnerStereo[0][loc_i];
4859 }
4860 }
4861 }
4862 return NULL__null;
4863}
4864
4865void DTrackCandidate_factory_CDC::DCDCTrackCircle::Strip_StereoSuperLayerSeed(unsigned int locSuperLayer)
4866{
4867 //assumes at most one stereo series of each type!!!
4868 deque<DCDCSuperLayerSeed*>::iterator locIterator;
4869 if(!dSuperLayerSeeds_OuterStereo.empty())
4870 {
4871 for(locIterator = dSuperLayerSeeds_OuterStereo[0].begin(); locIterator != dSuperLayerSeeds_OuterStereo[0].end(); ++locIterator)
4872 {
4873 if((*locIterator)->dSuperLayer != locSuperLayer)
4874 continue;
4875 dSuperLayerSeeds_OuterStereo[0].erase(locIterator);
4876 if(dSuperLayerSeeds_OuterStereo[0].empty())
4877 dSuperLayerSeeds_OuterStereo.clear();
4878 return;
4879 }
4880 }
4881 if(!dSuperLayerSeeds_InnerStereo.empty())
4882 {
4883 for(locIterator = dSuperLayerSeeds_InnerStereo[0].begin(); locIterator != dSuperLayerSeeds_InnerStereo[0].end(); ++locIterator)
4884 {
4885 if((*locIterator)->dSuperLayer != locSuperLayer)
4886 continue;
4887 dSuperLayerSeeds_InnerStereo[0].erase(locIterator);
4888 if(dSuperLayerSeeds_InnerStereo[0].empty())
4889 dSuperLayerSeeds_InnerStereo.clear();
4890 return;
4891 }
4892 }
4893}
4894
4895void DTrackCandidate_factory_CDC::DCDCTrackCircle::Add_LastSuperLayerSeed(DCDCSuperLayerSeed* locSuperLayerSeed)
4896{
4897 //assumes at most one stereo series of each type!!!
4898 unsigned int locSuperLayer = locSuperLayerSeed->dSuperLayer;
4899 if((locSuperLayer == 1) || (locSuperLayer == 4) || (locSuperLayer == 7))
4900 dSuperLayerSeeds_Axial.push_back(locSuperLayerSeed);
4901 else if((locSuperLayer == 2) || (locSuperLayer == 3))
4902 {
4903 if(dSuperLayerSeeds_InnerStereo.empty())
4904 dSuperLayerSeeds_InnerStereo.resize(1);
4905 dSuperLayerSeeds_InnerStereo[0].push_back(locSuperLayerSeed);
4906 }
4907 else //is super layer 5 or 6
4908 {
4909 unsigned int locLastAxialLayer = dSuperLayerSeeds_Axial.empty() ? 0 : dSuperLayerSeeds_Axial.back()->dSuperLayer;
4910 if(dSuperLayerSeeds_InnerStereo.empty() || (locLastAxialLayer == 4))
4911 {
4912 if(dSuperLayerSeeds_OuterStereo.empty())
4913 dSuperLayerSeeds_OuterStereo.resize(1);
4914 dSuperLayerSeeds_OuterStereo[0].push_back(locSuperLayerSeed);
4915 }
4916 else //put in inner stereo to keep combinations correct
4917 dSuperLayerSeeds_InnerStereo[0].push_back(locSuperLayerSeed);
4918 }
4919}
4920
4921void DTrackCandidate_factory_CDC::DCDCTrackCircle::Truncate_Circle(unsigned int locNewLastSuperLayer)
4922{
4923 //truncate this circle by rejecting all super layers down to locNewLastSuperLayer
4924 //DOES NOT recycle any memory (these seeds may be used by other circles!!)
4925 for(size_t loc_i = 0; loc_i < dSuperLayerSeeds_Axial.size(); ++loc_i)
4926 {
4927 if(dSuperLayerSeeds_Axial[loc_i]->dSuperLayer <= locNewLastSuperLayer)
4928 continue;
4929 ((loc_i == 0) ? dSuperLayerSeeds_Axial.clear() : dSuperLayerSeeds_Axial.resize(loc_i));
4930 break;
4931 }
4932
4933 //outer stereo
4934 deque<deque<DCDCSuperLayerSeed*> >::iterator locIterator, locIterator2;
4935 if(locNewLastSuperLayer < 5)
4936 dSuperLayerSeeds_OuterStereo.clear();
4937 else if(locNewLastSuperLayer < 7)
4938 {
4939 bool locClippedEveryStereoSeedFlag = true;
4940 for(locIterator = dSuperLayerSeeds_OuterStereo.begin(); locIterator != dSuperLayerSeeds_OuterStereo.end();)
4941 {
4942 deque<DCDCSuperLayerSeed*>& locSeedSeries = *locIterator;
4943 bool locClippedstereoSeriesFlag = false;
4944 for(size_t loc_j = 0; loc_j < locSeedSeries.size(); ++loc_j)
4945 {
4946 if(locSeedSeries[loc_j]->dSuperLayer <= locNewLastSuperLayer)
4947 continue;
4948 locClippedstereoSeriesFlag = true;
4949 if(loc_j == 0)
4950 {
4951 locSeedSeries.clear();
4952 break;
4953 }
4954 locSeedSeries.resize(loc_j);
4955 //now, check if another seed series is exactly like this one: if so, clear it
4956 for(locIterator2 = dSuperLayerSeeds_OuterStereo.begin(); locIterator2 != dSuperLayerSeeds_OuterStereo.end(); ++locIterator2)
4957 {
4958 if(locIterator2 == locIterator)
4959 continue;
4960 deque<DCDCSuperLayerSeed*>& locSeedSeries2 = *locIterator2;
4961 if(locSeedSeries == locSeedSeries2)
4962 {
4963 locSeedSeries.clear();
4964 break;
4965 }
4966 }
4967 break;
4968 }
4969 if(!locClippedstereoSeriesFlag)
4970 locClippedEveryStereoSeedFlag = false;
4971 (locSeedSeries.empty() ? (locIterator = dSuperLayerSeeds_OuterStereo.erase(locIterator)) : ++locIterator);
4972 }
4973 if(locClippedEveryStereoSeedFlag)
4974 dHasNonTruncatedSeedsFlag_OuterStereo = false;
4975 }
4976
4977 //inner stereo
4978 if(locNewLastSuperLayer < 2)
4979 {
4980 dSuperLayerSeeds_InnerStereo.clear();
4981 return;
4982 }
4983 else if(locNewLastSuperLayer < 7) //7 instead of 4: could be outer super layers in inner (if SL4 is missing)
4984 {
4985 bool locClippedEveryStereoSeedFlag = true;
4986 for(locIterator = dSuperLayerSeeds_InnerStereo.begin(); locIterator != dSuperLayerSeeds_InnerStereo.end();)
4987 {
4988 deque<DCDCSuperLayerSeed*>& locSeedSeries = *locIterator;
4989 bool locClippedstereoSeriesFlag = false;
4990 for(size_t loc_j = 0; loc_j < locSeedSeries.size(); ++loc_j)
4991 {
4992 if(locSeedSeries[loc_j]->dSuperLayer <= locNewLastSuperLayer)
4993 continue;
4994 locClippedstereoSeriesFlag = true;
4995 if(loc_j == 0)
4996 {
4997 locSeedSeries.clear();
4998 break;
4999 }
5000 locSeedSeries.resize(loc_j);
5001 //now, check if another seed series is exactly like this one: if so, clear it
5002 for(locIterator2 = dSuperLayerSeeds_InnerStereo.begin(); locIterator2 != dSuperLayerSeeds_InnerStereo.end(); ++locIterator2)
5003 {
5004 if(locIterator2 == locIterator)
5005 continue;
5006 deque<DCDCSuperLayerSeed*>& locSeedSeries2 = *locIterator2;
5007 if(locSeedSeries == locSeedSeries2)
5008 {
5009 locSeedSeries.clear();
5010 break;
5011 }
5012 }
5013 break;
5014 }
5015 if(!locClippedstereoSeriesFlag)
5016 locClippedEveryStereoSeedFlag = false;
5017 (locSeedSeries.empty() ? (locIterator = dSuperLayerSeeds_InnerStereo.erase(locIterator)) : ++locIterator);
5018 }
5019 if(locClippedEveryStereoSeedFlag)
5020 dHasNonTruncatedSeedsFlag_InnerStereo = false;
5021 }
5022}
5023
5024void DTrackCandidate_factory_CDC::DCDCTrackCircle::Absorb_TrackCircle(const DCDCTrackCircle* locTrackCircle)
5025{
5026 //used when merging track circles: this track circle will absorb the stereo combinations from the other one
5027 for(size_t loc_i = 0; loc_i < locTrackCircle->dSuperLayerSeeds_InnerStereo.size(); ++loc_i)
5028 {
5029 const deque<DCDCSuperLayerSeed*>& locSeedSeries = locTrackCircle->dSuperLayerSeeds_InnerStereo[loc_i];
5030 bool locComboAlreadyPresentFlag = false;
5031 for(size_t loc_j = 0; loc_j < dSuperLayerSeeds_InnerStereo.size(); ++loc_j)
5032 {
5033 if(locSeedSeries == dSuperLayerSeeds_InnerStereo[loc_j])
5034 {
5035 locComboAlreadyPresentFlag = true;
5036 break;
5037 }
5038 else if((locSeedSeries.size() == 1) && (locSeedSeries[0] == dSuperLayerSeeds_InnerStereo[loc_j][0]))
5039 {
5040 locComboAlreadyPresentFlag = true; //is a subset of an existing combo
5041 break;
5042 }
5043 }
5044 if(!locComboAlreadyPresentFlag)
5045 dSuperLayerSeeds_InnerStereo.push_back(locSeedSeries);
5046 }
5047
5048 for(size_t loc_i = 0; loc_i < locTrackCircle->dSuperLayerSeeds_OuterStereo.size(); ++loc_i)
5049 {
5050 const deque<DCDCSuperLayerSeed*>& locSeedSeries = locTrackCircle->dSuperLayerSeeds_OuterStereo[loc_i];
5051 bool locComboAlreadyPresentFlag = false;
5052 for(size_t loc_j = 0; loc_j < dSuperLayerSeeds_OuterStereo.size(); ++loc_j)
5053 {
5054 if(locSeedSeries == dSuperLayerSeeds_OuterStereo[loc_j])
5055 {
5056 locComboAlreadyPresentFlag = true;
5057 break;
5058 }
5059 else if((locSeedSeries.size() == 1) && (locSeedSeries[0] == dSuperLayerSeeds_OuterStereo[loc_j][0]))
5060 {
5061 locComboAlreadyPresentFlag = true; //is a subset of an existing combo
5062 break;
5063 }
5064 }
5065 if(!locComboAlreadyPresentFlag)
5066 dSuperLayerSeeds_OuterStereo.push_back(locSeedSeries);
5067 }
5068
5069 if(locTrackCircle->dHasNonTruncatedSeedsFlag_InnerStereo)
5070 dHasNonTruncatedSeedsFlag_InnerStereo = true;
5071 if(locTrackCircle->dHasNonTruncatedSeedsFlag_OuterStereo)
5072 dHasNonTruncatedSeedsFlag_OuterStereo = true;
5073
5074 for(size_t loc_i = 0; loc_i < locTrackCircle->dTruncationSourceCircles.size(); ++loc_i)
5075 {
5076 bool locIsAlreadyTruncationSourceFlag = false;
5077 for(size_t loc_j = 0; loc_j < dTruncationSourceCircles.size(); ++loc_j)
5078 {
5079 if(locTrackCircle->dTruncationSourceCircles[loc_i] != dTruncationSourceCircles[loc_j])
5080 continue;
5081 locIsAlreadyTruncationSourceFlag = true;
5082 break;
5083 }
5084 if(!locIsAlreadyTruncationSourceFlag)
5085 dTruncationSourceCircles.push_back(locTrackCircle->dTruncationSourceCircles[loc_i]);
5086 }
5087}
5088
5089bool DTrackCandidate_factory_CDC::DCDCTrackCircle::Check_IfInputIsSubset(const DCDCTrackCircle* locTrackCircle)
5090{
5091 //returns false if they are effectively identical
5092 if(locTrackCircle->dSuperLayerSeeds_Axial.empty())
5093 return false;
5094 if(locTrackCircle->Get_LastSuperLayerSeed()->dSuperLayer == 7)
5095 return false; //can't be subset if hasn't been truncated yet
5096 if(locTrackCircle->dSuperLayerSeeds_Axial.size() >= dSuperLayerSeeds_Axial.size())
5097 return false; //can't be subset if same # or greater of axial super layers (if identical should merge them instead)
5098
5099 for(size_t loc_i = 0; loc_i < locTrackCircle->dSuperLayerSeeds_Axial.size(); ++loc_i)
5100 {
5101 DCDCSuperLayerSeed* locSuperLayerSeed = locTrackCircle->dSuperLayerSeeds_Axial[loc_i];
5102 if(Get_SuperLayerSeed(locSuperLayerSeed->dSuperLayer) != locSuperLayerSeed)
5103 return false;
5104 }
5105 //all axial seeds are a subset, now check the stereo dHasNonTruncatedSeedsFlag flags
5106 DCDCSuperLayerSeed* locLastSuperLayerSeed = locTrackCircle->Get_LastSuperLayerSeed();
5107 if((locLastSuperLayerSeed->dSuperLayer == 1) || (locLastSuperLayerSeed->dSuperLayer == 4))
5108 return true;
5109
5110 DCDCSuperLayerSeed* locLastAxialSuperLayerSeed = locTrackCircle->dSuperLayerSeeds_Axial.back();
5111 if(locLastAxialSuperLayerSeed->dSuperLayer == 4)
5112 return locTrackCircle->dHasNonTruncatedSeedsFlag_OuterStereo;
5113 else
5114 return locTrackCircle->dHasNonTruncatedSeedsFlag_InnerStereo;
5115}
5116
5117void DTrackCandidate_factory_CDC::DCDCTrackCircle::Get_AllStereoSuperLayerSeeds(deque<DCDCSuperLayerSeed*>& locStereoSuperLayerSeeds)
5118{
5119 //assumes there is only one seed series
5120 locStereoSuperLayerSeeds.clear();
5121 if(!dSuperLayerSeeds_InnerStereo.empty())
5122 locStereoSuperLayerSeeds = dSuperLayerSeeds_InnerStereo[0];
5123 if(!dSuperLayerSeeds_OuterStereo.empty())
5124 locStereoSuperLayerSeeds.insert(locStereoSuperLayerSeeds.begin(), dSuperLayerSeeds_OuterStereo[0].begin(), dSuperLayerSeeds_OuterStereo[0].end());
5125}
5126
5127unsigned int DTrackCandidate_factory_CDC::DCDCTrackCircle::Get_NumStereoSuperLayerSeeds(void)
5128{
5129 //assumes there is only one seed series
5130 unsigned int locNumStereoSuperLayerSeeds = 0;
5131 if(!dSuperLayerSeeds_InnerStereo.empty())
5132 locNumStereoSuperLayerSeeds += dSuperLayerSeeds_InnerStereo[0].size();
5133 if(!dSuperLayerSeeds_OuterStereo.empty())
5134 locNumStereoSuperLayerSeeds += dSuperLayerSeeds_OuterStereo[0].size();
5135 return locNumStereoSuperLayerSeeds;
5136}
5137
5138//-------------------------------------------------------------------------
5139// Routines for fitting a line to the stereo data
5140//-------------------------------------------------------------------------
5141// Compute the chi^2 for a line fit given errors in both s and z. Also
5142// computes current best guess for the scaled intercept z0.
5143// Taken from Numerical Recipes in C (2nd ed.), p. 670.
5144double DTrackCandidate_factory_CDC::DCDCLineFit::ChiXY(double lambda)
5145{
5146 double tanl=tan(lambda);
5147 double sumw=0.,avg_s=0.,avg_z=0.,my_chi2=0.;
5148 for (unsigned i=0;i<n;i++){
5149 w[i]=1./(tanl*tanl*var_s[i]+var_z[i]);
5150 sumw+=w[i];
5151 avg_s+=w[i]*s[i];
5152 avg_z+=w[i]*z[i];
5153 }
5154 avg_s/=sumw;
5155 avg_z/=sumw;
5156 z0=avg_z-tanl*avg_s;
5157 for (unsigned int i=0;i<n;i++){
5158 double temp=z[i]-z0-tanl*s[i];
5159 my_chi2+=w[i]*temp*temp;
5160 }
5161 return my_chi2;
5162}
5163
5164// Routine to bracket the minimum chi^2, from Numerical Recipes in C (2nd ed.),
5165// pp. 400-401.
5166#define SHFT(w,x,y,z)(w)=(x);(x)=(y);(y)=(z) (w)=(x);(x)=(y);(y)=(z)
5167#define SIGN(x,y)((y)>=0.0 ? fabs(x):-fabs(x)) ((y)>=0.0 ? fabs(x):-fabs(x))
5168void DTrackCandidate_factory_CDC::DCDCLineFit::BracketMinimumChisq(double &a,double &b,double &c,double &chi2a,double &chi2b,double &chi2c)
5169{
5170 const double GOLD=1.618034;
5171 const double GLIMIT=100.0;
5172
5173 chi2a=ChiXY(a);
5174 chi2b=ChiXY(b);
5175 double chi2u=0.;
5176 if (chi2b>chi2a){
5177 double dummy=0.;
5178 SHFT(dummy,a,b,dummy)(dummy)=(a);(a)=(b);(b)=(dummy);
5179 SHFT(dummy,chi2b,chi2a,dummy)(dummy)=(chi2b);(chi2b)=(chi2a);(chi2a)=(dummy);
5180 }
5181 c=b+GOLD*(b-a);
5182 chi2c=ChiXY(c);
5183 while (chi2b>chi2c){
5184 double r=(b-a)*(chi2b-chi2c);
5185 double q=(b-c)*(chi2b-chi2a);
5186 double q_minus_r=q-r;
5187 double fabs_q_minus_r=fabs(q_minus_r);
5188 double max=(fabs_q_minus_r>1.e-20)?fabs_q_minus_r:1.e-20;
5189 double u=b-((b-c)*q-(b-a)*r)/(2.*SIGN(max,q_minus_r)((q_minus_r)>=0.0 ? fabs(max):-fabs(max)));
5190 double ulim=b+GLIMIT*(c-b);
5191 if ((b-u)*(u-c)>0.0){
5192 chi2u=ChiXY(u);
5193 if (chi2u<chi2c){
5194 a=b;
5195 b=u;
5196 chi2a=chi2b;
5197 chi2b=chi2u;
5198 return;
5199 }
5200 else if (chi2u>chi2b){
5201 c=u;
5202 chi2c=chi2u;
5203 return;
5204 }
5205 u=c+GOLD*(c-b);
5206 chi2u=ChiXY(u);
5207 }
5208 else if ((c-u)*(u-ulim)>0.0){
5209 chi2u=ChiXY(u);
5210 if (chi2u<chi2c){
5211 SHFT(b,c,u,c+GOLD*(c-b))(b)=(c);(c)=(u);(u)=(c+GOLD*(c-b));
5212 SHFT(chi2b,chi2c,chi2u,ChiXY(u))(chi2b)=(chi2c);(chi2c)=(chi2u);(chi2u)=(ChiXY(u));
5213 }
5214 }
5215 else if ((u-ulim)*(ulim-c)>=0.0){
5216 u=ulim;
5217 chi2u=ChiXY(u);
5218 }
5219 else{
5220 u=c+GOLD*(c-b);
5221 chi2u=ChiXY(u);
5222 }
5223 SHFT(a,b,c,u)(a)=(b);(b)=(c);(c)=(u);
5224 SHFT(chi2a,chi2b,chi2c,chi2u)(chi2a)=(chi2b);(chi2b)=(chi2c);(chi2c)=(chi2u);
5225 }
5226}
5227
5228// Use Brent's algorithm to find the "true" (within tolerance) minimum chi^2
5229// after bracketting. Taken from Numerical Recipes in C (2nd. Ed.), pp. 404-405.
5230double DTrackCandidate_factory_CDC::DCDCLineFit::FindMinimumChisq(double ax,double bx, double cx, double &xmin)
5231{
5232 const double CGOLD=0.3819660;
5233 double a=(ax<cx)?ax:cx;
5234 double b=(ax>cx)?ax:cx;
5235 double x=bx,w=bx,v=bx;
5236 double fx=ChiXY(x),fv=fx,fw=fx,fu=0.;
5237 double tol=1e-3,err=0.0,d=0.,u=0.;
5238 for (int iter=1;iter<=100;iter++){
5239 double xm=0.5*(a+b);
5240 double tol1=tol*fabs(x)+1e-10;
5241 double tol2=2.0*tol1;
5242 if (fabs(x-xm)<=(tol2-0.5*(b-a))){
5243 xmin=x;
5244 return fx;
5245 }
5246 if (fabs(err)>tol1){
5247 double r=(x-w)*(fx-fv);
5248 double q=(x-v)*(fx-fw);
5249 double p=(x-v)*q-(x-w)*r;
5250 q=2.0*(q-r);
5251 if (q>0.0) p=-p;
5252 q=fabs(q);
5253 double etemp=err;
5254 err=d;
5255 if (fabs(p)>=fabs(0.5*q*etemp) || p<=q*(a-x)|| p>=q*(b-x)){
5256 d=CGOLD*(err=(x>=xm ? a-x : b-x));
5257 }
5258 else{
5259 d=p/q;
5260 u=x+d;
5261 if (u-a < tol2 || b-u < tol2) d=SIGN(tol1,xm-x)((xm-x)>=0.0 ? fabs(tol1):-fabs(tol1));
5262 }
5263 } else {
5264 d=CGOLD*(err=(x>=xm ? a-x : b-x ));
5265 }
5266 u=(fabs(d)>=tol1 ? x+d : x+SIGN(tol1,d)((d)>=0.0 ? fabs(tol1):-fabs(tol1)));
5267 fu=ChiXY(u);
5268 if (fu<=fx){
5269 if (u>=x) a=x;
5270 else b=x;
5271 SHFT(v,w,x,u)(v)=(w);(w)=(x);(x)=(u);
5272 SHFT(fv,fw,fx,fu)(fv)=(fw);(fw)=(fx);(fx)=(fu);
5273 }
5274 else{
5275 if (u<x) a=u;
5276 else b=u;
5277 if (fu<=fw || w==x){
5278 v=w;
5279 w=u;
5280 fv=fw;
5281 fw=fu;
5282 }
5283 else if (fu<=fv || v==x || v==w){
5284 v=u;
5285 fv=fu;
5286 }
5287 }
5288 }
5289 xmin=x;
5290 return fx;
5291}
5292