Bug Summary

File:alld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h
Warning:line 398, column 7
Null pointer passed to 2nd parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -main-file-name DTrackCandidate_factory_CDC.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0 -D HAVE_CCDB -D HAVE_RCDB -D HAVE_EVIO -D HAVE_TMVA=1 -D RCDB_MYSQL=1 -D RCDB_SQLITE=1 -D SQLITE_USE_LEGACY_STRUCT=ON -I .Linux_CentOS7.7-x86_64-gcc4.8.5/libraries/TRACKING -I libraries/TRACKING -I . -I libraries -I libraries/include -I /w/halld-scifs17exp/home/sdobbs/clang/halld_recon/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I external/xstream/include -I /usr/include/tirpc -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/root/root-6.08.06/include -I /w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/ccdb/ccdb_1.06.06/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/rcdb/rcdb_0.06.00/cpp/include -I /usr/include/mysql -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/sqlitecpp/SQLiteCpp-2.2.0^bs130/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/sqlite/sqlite-3.13.0^bs130/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/hdds/hdds-4.9.0/Linux_CentOS7.7-x86_64-gcc4.8.5/src -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/xerces-c/xerces-c-3.1.4/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/evio/evio-4.4.6/Linux-x86_64/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/backward -internal-isystem /usr/local/include -internal-isystem /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/sdobbs/work/clang/halld_recon/src -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-01-21-110224-160369-1 -x c++ libraries/TRACKING/DTrackCandidate_factory_CDC.cc

libraries/TRACKING/DTrackCandidate_factory_CDC.cc

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

/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h

1// $Id: JEventLoop.h 1763 2006-05-10 14:29:25Z davidl $
2//
3// File: JEventLoop.h
4// Created: Wed Jun 8 12:30:51 EDT 2005
5// Creator: davidl (on Darwin wire129.jlab.org 7.8.0 powerpc)
6//
7
8#ifndef _JEventLoop_
9#define _JEventLoop_
10
11#include <sys/time.h>
12
13#include <vector>
14#include <list>
15#include <string>
16#include <utility>
17#include <typeinfo>
18#include <string.h>
19#include <map>
20#include <utility>
21using std::vector;
22using std::list;
23using std::string;
24using std::type_info;
25
26#include <JANA/jerror.h>
27#include <JANA/JObject.h>
28#include <JANA/JException.h>
29#include <JANA/JEvent.h>
30#include <JANA/JThread.h>
31#include <JANA/JFactory_base.h>
32#include <JANA/JCalibration.h>
33#include <JANA/JGeometry.h>
34#include <JANA/JResourceManager.h>
35#include <JANA/JStreamLog.h>
36
37// The following is here just so we can use ROOT's THtml class to generate documentation.
38#include "cint.h"
39
40
41// Place everything in JANA namespace
42namespace jana{
43
44
45template<class T> class JFactory;
46class JApplication;
47class JEventProcessor;
48
49
50class JEventLoop{
51 public:
52
53 friend class JApplication;
54
55 enum data_source_t{
56 DATA_NOT_AVAILABLE = 1,
57 DATA_FROM_CACHE,
58 DATA_FROM_SOURCE,
59 DATA_FROM_FACTORY
60 };
61
62 typedef struct{
63 string caller_name;
64 string caller_tag;
65 string callee_name;
66 string callee_tag;
67 double start_time;
68 double end_time;
69 data_source_t data_source;
70 }call_stack_t;
71
72 typedef struct{
73 const char* factory_name;
74 string tag;
75 const char* filename;
76 int line;
77 }error_call_stack_t;
78
79 JEventLoop(JApplication *app); ///< Constructor
80 virtual ~JEventLoop(); ////< Destructor
81 virtual const char* className(void){return static_className();}
82 static const char* static_className(void){return "JEventLoop";}
83
84 JApplication* GetJApplication(void) const {return app;} ///< Get pointer to the JApplication object
85 void RefreshProcessorListFromJApplication(void); ///< Re-copy the list of JEventProcessors from JApplication
86 virtual jerror_t AddFactory(JFactory_base* factory); ///< Add a factory
87 jerror_t RemoveFactory(JFactory_base* factory); ///< Remove a factory
88 JFactory_base* GetFactory(const string data_name, const char *tag="", bool allow_deftag=true); ///< Get a specific factory pointer
89 vector<JFactory_base*> GetFactories(void) const {return factories;} ///< Get all factory pointers
90 void GetFactoryNames(vector<string> &factorynames); ///< Get names of all factories in name:tag format
91 void GetFactoryNames(map<string,string> &factorynames); ///< Get names of all factories in map with key=name, value=tag
92 map<string,string> GetDefaultTags(void) const {return default_tags;}
93 jerror_t ClearFactories(void); ///< Reset all factories in preparation for next event.
94 jerror_t PrintFactories(int sparsify=0); ///< Print a list of all factories.
95 jerror_t Print(const string data_name, const char *tag=""); ///< Print the data of the given type
96
97 JCalibration* GetJCalibration();
98 template<class T> bool GetCalib(string namepath, map<string,T> &vals);
99 template<class T> bool GetCalib(string namepath, vector<T> &vals);
100 template<class T> bool GetCalib(string namepath, T &val);
101
102 JGeometry* GetJGeometry();
103 template<class T> bool GetGeom(string namepath, map<string,T> &vals);
104 template<class T> bool GetGeom(string namepath, T &val);
105
106 JResourceManager* GetJResourceManager(void);
107 string GetResource(string namepath);
108 template<class T> bool GetResource(string namepath, T vals, int event_number=0);
109
110 void Initialize(void); ///< Do initializations just before event processing starts
111 jerror_t Loop(void); ///< Loop over events
112 jerror_t OneEvent(uint64_t event_number); ///< Process a specific single event (if source supports it)
113 jerror_t OneEvent(void); ///< Process a single event
114 inline void Pause(void){pause = 1;} ///< Pause event processing
115 inline void Resume(void){pause = 0;} ///< Resume event processing
116 inline void Quit(void){quit = 1;} ///< Clean up and exit the event loop
117 inline bool GetQuit(void) const {return quit;}
118 void QuitProgram(void);
119
120 // Support for random access of events
121 bool HasRandomAccess(void);
122 void AddToEventQueue(uint64_t event_number){ next_events_to_process.push_back(event_number); }
123 void AddToEventQueue(list<uint64_t> &event_numbers) { next_events_to_process.insert(next_events_to_process.end(), event_numbers.begin(), event_numbers.end()); }
124 list<uint64_t> GetEventQueue(void){ return next_events_to_process; }
125 void ClearEventQueue(void){ next_events_to_process.clear(); }
126
127 template<class T> JFactory<T>* GetSingle(const T* &t, const char *tag="", bool exception_if_not_one=true); ///< Get pointer to first data object from (source or factory).
128 template<class T> JFactory<T>* Get(vector<const T*> &t, const char *tag="", bool allow_deftag=true); ///< Get data object pointers from (source or factory)
129 template<class T> JFactory<T>* GetFromFactory(vector<const T*> &t, const char *tag="", data_source_t &data_source=null_data_source, bool allow_deftag=true); ///< Get data object pointers from factory
130 template<class T> jerror_t GetFromSource(vector<const T*> &t, JFactory_base *factory=NULL__null); ///< Get data object pointers from source.
131 inline JEvent& GetJEvent(void){return event;} ///< Get pointer to the current JEvent object.
132 inline void SetJEvent(JEvent *event){this->event = *event;} ///< Set the JEvent pointer.
133 inline void SetAutoFree(int auto_free){this->auto_free = auto_free;} ///< Set the Auto-Free flag on/off
134 inline pthread_t GetPThreadID(void) const {return pthread_id;} ///< Get the pthread of the thread to which this JEventLoop belongs
135 double GetInstantaneousRate(void) const {return rate_instantaneous;} ///< Get the current event processing rate
136 double GetIntegratedRate(void) const {return rate_integrated;} ///< Get the current event processing rate
137 double GetLastEventProcessingTime(void) const {return delta_time_single;}
138 unsigned int GetNevents(void) const {return Nevents;}
139
140 inline bool CheckEventBoundary(uint64_t event_numberA, uint64_t event_numberB);
141
142 inline bool GetCallStackRecordingStatus(void){ return record_call_stack; }
143 inline void DisableCallStackRecording(void){ record_call_stack = false; }
144 inline void EnableCallStackRecording(void){ record_call_stack = true; }
145 inline void CallStackStart(JEventLoop::call_stack_t &cs, const string &caller_name, const string &caller_tag, const string callee_name, const string callee_tag);
146 inline void CallStackEnd(JEventLoop::call_stack_t &cs);
147 inline vector<call_stack_t> GetCallStack(void){return call_stack;} ///< Get the current factory call stack
148 inline void AddToCallStack(call_stack_t &cs){if(record_call_stack) call_stack.push_back(cs);} ///< Add specified item to call stack record but only if record_call_stack is true
149 inline void AddToErrorCallStack(error_call_stack_t &cs){error_call_stack.push_back(cs);} ///< Add layer to the factory call stack
150 inline vector<error_call_stack_t> GetErrorCallStack(void){return error_call_stack;} ///< Get the current factory error call stack
151 void PrintErrorCallStack(void); ///< Print the current factory call stack
152
153 const JObject* FindByID(JObject::oid_t id); ///< Find a data object by its identifier.
154 template<class T> const T* FindByID(JObject::oid_t id); ///< Find a data object by its type and identifier
155 JFactory_base* FindOwner(const JObject *t); ///< Find the factory that owns a data object by pointer
156 JFactory_base* FindOwner(JObject::oid_t id); ///< Find a factory that owns a data object by identifier
157
158 // User defined references
159 template<class T> void SetRef(T *t); ///< Add a user reference to this JEventLoop (must be a pointer)
160 template<class T> T* GetRef(void); ///< Get a user-defined reference of a specific type
161 template<class T> vector<T*> GetRefsT(void); ///< Get all user-defined refrences of a specicif type
162 vector<pair<const char*, void*> > GetRefs(void){ return user_refs; } ///< Get copy of full list of user-defined references
163 template<class T> void RemoveRef(T *t); ///< Remove user reference from list
164
165 // Convenience methods wrapping JEvent methods of same name
166 uint64_t GetStatus(void){return event.GetStatus();}
167 bool GetStatusBit(uint32_t bit){return event.GetStatusBit(bit);}
168 bool SetStatusBit(uint32_t bit, bool val=true){return event.SetStatusBit(bit, val);}
169 bool ClearStatusBit(uint32_t bit){return event.ClearStatusBit(bit);}
170 void ClearStatus(void){event.ClearStatus();}
171 void SetStatusBitDescription(uint32_t bit, string description){event.SetStatusBitDescription(bit, description);}
172 string GetStatusBitDescription(uint32_t bit){return event.GetStatusBitDescription(bit);}
173 void GetStatusBitDescriptions(map<uint32_t, string> &status_bit_descriptions){return event.GetStatusBitDescriptions(status_bit_descriptions);}
174 string StatusWordToString(void);
175
176 private:
177 JEvent event;
178 vector<JFactory_base*> factories;
179 vector<JEventProcessor*> processors;
180 vector<error_call_stack_t> error_call_stack;
181 vector<call_stack_t> call_stack;
182 JApplication *app;
183 JThread *jthread;
184 bool initialized;
185 bool print_parameters_called;
186 int pause;
187 int quit;
188 int auto_free;
189 pthread_t pthread_id;
190 map<string, string> default_tags;
191 vector<pair<string,string> > auto_activated_factories;
192 bool record_call_stack;
193 string caller_name;
194 string caller_tag;
195 vector<uint64_t> event_boundaries;
196 int32_t event_boundaries_run; ///< Run number boundaries were retrieved from (possbily 0)
197 list<uint64_t> next_events_to_process;
198
199 uint64_t Nevents; ///< Total events processed (this thread)
200 uint64_t Nevents_rate; ///< Num. events accumulated for "instantaneous" rate
201 double delta_time_single; ///< Time spent processing last event
202 double delta_time_rate; ///< Integrated time accumulated "instantaneous" rate (partial number of events)
203 double delta_time; ///< Total time spent processing events (this thread)
204 double rate_instantaneous; ///< Latest instantaneous rate
205 double rate_integrated; ///< Rate integrated over all events
206
207 static data_source_t null_data_source;
208
209 vector<pair<const char*, void*> > user_refs;
210};
211
212
213// The following is here just so we can use ROOT's THtml class to generate documentation.
214#ifdef G__DICTIONARY
215typedef JEventLoop::call_stack_t call_stack_t;
216typedef JEventLoop::error_call_stack_t error_call_stack_t;
217#endif
218
219#if !defined(__CINT__) && !defined(__CLING__)
220
221//-------------
222// GetSingle
223//-------------
224template<class T>
225JFactory<T>* JEventLoop::GetSingle(const T* &t, const char *tag, bool exception_if_not_one)
226{
227 /// This is a convenience method that can be used to get a pointer to the single
228 /// object of type T from the specified factory. It simply calls the Get(vector<...>) method
229 /// and copies the first pointer into "t" (or NULL if something other than 1 object is returned).
230 ///
231 /// This is intended to address the common situation in which there is an interest
232 /// in the event if and only if there is exactly 1 object of type T. If the event
233 /// has no objects of that type or more than 1 object of that type (for the specified
234 /// factory) then an exception of type "unsigned long" is thrown with the value
235 /// being the number of objects of type T. You can supress the exception by setting
236 /// exception_if_not_one to false. In that case, you will have to check if t==NULL to
237 /// know if the call succeeded.
238 vector<const T*> v;
239 JFactory<T> *fac = Get(v, tag);
240
241 if(v.size()!=1){
242 t = NULL__null;
243 if(exception_if_not_one) throw v.size();
244 }
245
246 t = v[0];
247
248 return fac;
249}
250
251//-------------
252// Get
253//-------------
254template<class T>
255JFactory<T>* JEventLoop::Get(vector<const T*> &t, const char *tag, bool allow_deftag)
256{
257 /// Retrieve or generate the array of objects of
258 /// type T for the curent event being processed
259 /// by this thread.
260 ///
261 /// By default, preference is given to reading the
262 /// objects from the data source(e.g. file) before generating
263 /// them in the factory. A flag exists in the factory
264 /// however to change this so that the factory is
265 /// given preference.
266 ///
267 /// Note that regardless of the setting of this flag,
268 /// the data are only either read in or generated once.
269 /// Ownership of the objects will always be with the
270 /// factory so subsequent calls will always return pointers to
271 /// the same data.
272 ///
273 /// If the factory is called on to generate the data,
274 /// it is done by calling the factory's Get() method
275 /// which, in turn, calls the evnt() method.
276 ///
277 /// First, we just call the GetFromFactory() method.
278 /// It will make the initial decision as to whether
279 /// it should look in the source first or not. If
280 /// it returns NULL, then the factory couldn't be
281 /// found so we automatically try the file.
282 ///
283 /// Note that if no factory exists to hold the objects
284 /// from the file, one can be created automatically
285 /// providing the <i>JANA:AUTOFACTORYCREATE</i>
286 /// configuration parameter is set.
287
288 // Check if a tag was specified for this data type to use for the
289 // default.
290 const char *mytag = tag
1.1
'tag' is not equal to NULL
1.1
'tag' is not equal to NULL
1.1
'tag' is not equal to NULL
==NULL__null ? "":tag; // protection against NULL tags
2
'?' condition is false
291 if(strlen(mytag)==0 && allow_deftag
2.1
'allow_deftag' is true
2.1
'allow_deftag' is true
2.1
'allow_deftag' is true
){
3
Taking true branch
292 map<string, string>::const_iterator iter = default_tags.find(T::static_className());
293 if(iter!=default_tags.end())tag = iter->second.c_str();
4
Assuming the condition is true
5
Taking true branch
6
Value assigned to 'tag'
294 }
295
296
297 // If we are trying to keep track of the call stack then we
298 // need to add a new call_stack_t object to the the list
299 // and initialize it with the start time and caller/callee
300 // info.
301 call_stack_t cs;
302
303 // Optionally record starting info of call stack entry
304 if(record_call_stack) CallStackStart(cs, caller_name, caller_tag, T::static_className(), tag);
7
Assuming field 'record_call_stack' is false
8
Taking false branch
305
306 // Get the data (or at least try to)
307 JFactory<T>* factory=NULL__null;
308 try{
309 factory = GetFromFactory(t, tag, cs.data_source, allow_deftag);
9
Passing value via 2nd parameter 'tag'
10
Calling 'JEventLoop::GetFromFactory'
310 if(!factory){
311 // No factory exists for this type and tag. It's possible
312 // that the source may be able to provide the objects
313 // but it will need a place to put them. We can create a
314 // dumb JFactory just to hold the data in case the source
315 // can provide the objects. Before we do though, make sure
316 // the user condones this via the presence of the
317 // "JANA:AUTOFACTORYCREATE" config parameter.
318 string p;
319 try{
320 gPARMS->GetParameter("JANA:AUTOFACTORYCREATE", p);
321 }catch(...){}
322 if(p.size()==0){
323 jout<<std::endl;
324 _DBG__std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<324<<std::endl
;
325 jout<<"No factory of type \""<<T::static_className()<<"\" with tag \""<<tag<<"\" exists."<<std::endl;
326 jout<<"If you are reading objects from a file, I can auto-create a factory"<<std::endl;
327 jout<<"of the appropriate type to hold the objects, but this feature is turned"<<std::endl;
328 jout<<"off by default. To turn it on, set the \"JANA:AUTOFACTORYCREATE\""<<std::endl;
329 jout<<"configuration parameter. This can usually be done by passing the"<<std::endl;
330 jout<<"following argument to the program from the command line:"<<std::endl;
331 jout<<std::endl;
332 jout<<" -PJANA:AUTOFACTORYCREATE=1"<<std::endl;
333 jout<<std::endl;
334 jout<<"Note that since the most commonly expected occurance of this situation."<<std::endl;
335 jout<<"is an error, the program will now throw an exception so that the factory."<<std::endl;
336 jout<<"call stack can be printed."<<std::endl;
337 jout<<std::endl;
338 throw exception();
339 }else{
340 AddFactory(new JFactory<T>(tag));
341 jout<<__FILE__"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"<<":"<<__LINE__341<<" Auto-created "<<T::static_className()<<":"<<tag<<" factory"<<std::endl;
342
343 // Now try once more. The GetFromFactory method will call
344 // GetFromSource since it's empty.
345 factory = GetFromFactory(t, tag, cs.data_source, allow_deftag);
346 }
347 }
348 }catch(exception &e){
349 // Uh-oh, an exception was thrown. Add us to the call stack
350 // and re-throw the exception
351 error_call_stack_t ecs;
352 ecs.factory_name = T::static_className();
353 ecs.tag = tag;
354 ecs.filename = NULL__null;
355 error_call_stack.push_back(ecs);
356 throw e;
357 }
358
359 // If recording the call stack, update the end_time field and add to stack
360 if(record_call_stack) CallStackEnd(cs);
361
362 return factory;
363}
364
365//-------------
366// GetFromFactory
367//-------------
368template<class T>
369JFactory<T>* JEventLoop::GetFromFactory(vector<const T*> &t, const char *tag, data_source_t &data_source, bool allow_deftag)
370{
371 // We need to find the factory providing data type T with
372 // tag given by "tag".
373 vector<JFactory_base*>::iterator iter=factories.begin();
374 JFactory<T> *factory = NULL__null;
375 string className(T::static_className());
376
377 // Check if a tag was specified for this data type to use for the
378 // default.
379 const char *mytag = tag==NULL__null ? "":tag; // protection against NULL tags
11
Assuming 'tag' is equal to NULL
12
Assuming pointer value is null
13
'?' condition is true
380 if(strlen(mytag)==0 && allow_deftag
13.1
'allow_deftag' is true
13.1
'allow_deftag' is true
13.1
'allow_deftag' is true
){
14
Taking true branch
381 map<string, string>::const_iterator iter = default_tags.find(className);
382 if(iter!=default_tags.end())tag = iter->second.c_str();
15
Assuming the condition is false
16
Taking false branch
383 }
384
385 for(; iter!=factories.end(); iter++){
17
Calling 'operator!=<jana::JFactory_base **, std::vector<jana::JFactory_base *>>'
20
Returning from 'operator!=<jana::JFactory_base **, std::vector<jana::JFactory_base *>>'
21
Loop condition is true. Entering loop body
386 // It turns out a long standing bug in g++ makes dynamic_cast return
387 // zero improperly when used on objects created on one side of
388 // a dynamically shared object (DSO) and the cast occurs on the
389 // other side. I saw bug reports ranging from 2001 to 2004. I saw
390 // saw it first-hand on LinuxEL4 using g++ 3.4.5. This is too bad
391 // since it is much more elegant (and safe) to use dynamic_cast.
392 // To avoid this problem which can occur with plugins, we check
393 // the name of the data classes are the same. (sigh)
394 //factory = dynamic_cast<JFactory<T> *>(*iter);
395 if(className == (*iter)->GetDataClassName())factory = (JFactory<T>*)(*iter);
22
Taking true branch
396 if(factory == NULL__null)continue;
23
Assuming 'factory' is not equal to NULL
24
Taking false branch
397 const char *factag = factory->Tag()==NULL__null ? "":factory->Tag();
25
Assuming the condition is true
26
'?' condition is true
398 if(!strcmp(factag, tag)){
27
Null pointer passed to 2nd parameter expecting 'nonnull'
399 break;
400 }else{
401 factory=NULL__null;
402 }
403 }
404
405 // If factory not found, just return now
406 if(!factory){
407 data_source = DATA_NOT_AVAILABLE;
408 return NULL__null;
409 }
410
411 // OK, we found the factory. If the evnt() routine has already
412 // been called, then just call the factory's Get() routine
413 // to return a copy of the existing data
414 if(factory->evnt_was_called()){
415 factory->CopyFrom(t);
416 data_source = DATA_FROM_CACHE;
417 return factory;
418 }
419
420 // Next option is to get the objects from the data source
421 if(factory->GetCheckSourceFirst()){
422 // If the object type/tag is found in the source, it
423 // will return NOERROR, even if there are zero instances
424 // of it. If it is not available in the source then it
425 // will return OBJECT_NOT_AVAILABLE.
426
427 jerror_t err = GetFromSource(t, factory);
428 if(err == NOERROR){
429 // A return value of NOERROR means the source had the objects
430 // even if there were zero of them.(If the source had no
431 // information about the objects OBJECT_NOT_AVAILABLE would
432 // have been returned.)
433 // The GetFromSource() call will eventually lead to a call to
434 // the GetObjects() method of the concrete class derived
435 // from JEventSource. That routine should copy the object
436 // pointers into the factory using the factory's CopyTo()
437 // method which also sets the evnt_called flag for the factory.
438 // Note also that the "t" vector is then filled with a call
439 // to the factory's CopyFrom() method in JEvent::GetObjects().
440 // All we need to do now is just set the factory pointers in
441 // the newly generated JObjects and return the factory pointer.
442
443 factory->SetFactoryPointers();
444 data_source = DATA_FROM_SOURCE;
445
446 return factory;
447 }
448 }
449
450 // OK. It looks like we have to have the factory make this.
451 // Get pointers to data from the factory.
452 factory->Get(t);
453 factory->SetFactoryPointers();
454 data_source = DATA_FROM_FACTORY;
455
456 return factory;
457}
458
459//-------------
460// GetFromSource
461//-------------
462template<class T>
463jerror_t JEventLoop::GetFromSource(vector<const T*> &t, JFactory_base *factory)
464{
465 /// This tries to get objects from the event source.
466 /// "factory" must be a valid pointer to a JFactory
467 /// object since that will take ownership of the objects
468 /// created by the source.
469 /// This should usually be called from JEventLoop::GetFromFactory
470 /// which is called from JEventLoop::Get. The latter will
471 /// create a dummy JFactory of the proper flavor and tag if
472 /// one does not already exist so if objects exist in the
473 /// file without a corresponding factory to create them, they
474 /// can still be used.
475 if(!factory)throw OBJECT_NOT_AVAILABLE;
476
477 return event.GetObjects(t, factory);
478}
479
480//-------------
481// CallStackStart
482//-------------
483inline void JEventLoop::CallStackStart(JEventLoop::call_stack_t &cs, const string &caller_name, const string &caller_tag, const string callee_name, const string callee_tag)
484{
485 /// This is used to fill initial info into a call_stack_t stucture
486 /// for recording the call stack. It should be matched with a call
487 /// to CallStackEnd. It is normally called from the Get() method
488 /// above, but may also be used by external actors to manipulate
489 /// the call stack (presumably for good and not evil).
490
491 struct itimerval tmr;
492 getitimer(ITIMER_PROFITIMER_PROF, &tmr);
493
494 cs.caller_name = this->caller_name;
495 cs.caller_tag = this->caller_tag;
496 this->caller_name = cs.callee_name = callee_name;
497 this->caller_tag = cs.callee_tag = callee_tag;
498 cs.start_time = tmr.it_value.tv_sec + tmr.it_value.tv_usec/1.0E6;
499}
500
501//-------------
502// CallStackEnd
503//-------------
504inline void JEventLoop::CallStackEnd(JEventLoop::call_stack_t &cs)
505{
506 /// Complete a call stack entry. This should be matched
507 /// with a previous call to CallStackStart which was
508 /// used to fill the cs structure.
509
510 struct itimerval tmr;
511 getitimer(ITIMER_PROFITIMER_PROF, &tmr);
512 cs.end_time = tmr.it_value.tv_sec + tmr.it_value.tv_usec/1.0E6;
513 caller_name = cs.caller_name;
514 caller_tag = cs.caller_tag;
515 call_stack.push_back(cs);
516}
517
518//-------------
519// CheckEventBoundary
520//-------------
521inline bool JEventLoop::CheckEventBoundary(uint64_t event_numberA, uint64_t event_numberB)
522{
523 /// Check whether the two event numbers span one or more boundaries
524 /// in the calibration/conditions database for the current run number.
525 /// Return true if they do and false if they don't. The first parameter
526 /// "event_numberA" is also checked if it lands on a boundary in which
527 /// case true is also returned. If event_numberB lands on a boundary,
528 /// but event_numberA does not, then false is returned.
529 ///
530 /// This method is not expected to be called by a user. It is, however called,
531 /// everytime a JFactory's Get() method is called.
532
533 // Make sure our copy of the boundaries is up to date
534 if(event.GetRunNumber()!=event_boundaries_run){
535 event_boundaries.clear(); // in case we can't get the JCalibration pointer
536 JCalibration *jcalib = GetJCalibration();
537 if(jcalib)jcalib->GetEventBoundaries(event_boundaries);
538 event_boundaries_run = event.GetRunNumber();
539 }
540
541 // Loop over boundaries
542 for(unsigned int i=0; i<event_boundaries.size(); i++){
543 uint64_t eb = event_boundaries[i];
544 if((eb - event_numberA)*(eb - event_numberB) < 0.0 || eb==event_numberA){ // think about it ....
545 // events span a boundary or is on a boundary. Return true
546 return true;
547 }
548 }
549
550 return false;
551}
552
553//-------------
554// FindByID
555//-------------
556template<class T>
557const T* JEventLoop::FindByID(JObject::oid_t id)
558{
559 /// This is a templated method that can be used in place
560 /// of the non-templated FindByID(oid_t) method if one knows
561 /// the class of the object with the specified id.
562 /// This method is faster than calling the non-templated
563 /// FindByID and dynamic_cast-ing the JObject since
564 /// this will only search the objects of factories that
565 /// produce the desired data type.
566 /// This method will cast the JObject pointer to one
567 /// of the specified type. To use this method,
568 /// a type is specified in the call as follows:
569 ///
570 /// const DMyType *t = loop->FindByID<DMyType>(id);
571
572 // Loop over factories looking for ones that provide
573 // specified data type.
574 for(unsigned int i=0; i<factories.size(); i++){
575 if(factories[i]->GetDataClassName() != T::static_className())continue;
576
577 // This factory provides data of type T. Search it for
578 // the object with the specified id.
579 const JObject *my_obj = factories[i]->GetByID(id);
580 if(my_obj)return dynamic_cast<const T*>(my_obj);
581 }
582
583 return NULL__null;
584}
585
586//-------------
587// GetCalib (map)
588//-------------
589template<class T>
590bool JEventLoop::GetCalib(string namepath, map<string,T> &vals)
591{
592 /// Get the JCalibration object from JApplication for the run number of
593 /// the current event and call its Get() method to get the constants.
594
595 // Note that we could do this by making "vals" a generic type T thus, combining
596 // this with the vector version below. However, doing this explicitly will make
597 // it easier for the user to understand how to call us.
598
599 vals.clear();
600
601 JCalibration *calib = GetJCalibration();
602 if(!calib){
603 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<603<<" "
<<"Unable to get JCalibration object for run "<<event.GetRunNumber()<<std::endl;
604 return true;
605 }
606
607 return calib->Get(namepath, vals, event.GetEventNumber());
608}
609
610//-------------
611// GetCalib (vector)
612//-------------
613template<class T> bool JEventLoop::GetCalib(string namepath, vector<T> &vals)
614{
615 /// Get the JCalibration object from JApplication for the run number of
616 /// the current event and call its Get() method to get the constants.
617
618 vals.clear();
619
620 JCalibration *calib = GetJCalibration();
621 if(!calib){
622 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<622<<" "
<<"Unable to get JCalibration object for run "<<event.GetRunNumber()<<std::endl;
623 return true;
624 }
625
626 return calib->Get(namepath, vals, event.GetEventNumber());
627}
628
629//-------------
630// GetCalib (single)
631//-------------
632template<class T> bool JEventLoop::GetCalib(string namepath, T &val)
633{
634 /// This is a convenience method for getting a single entry. It
635 /// simply calls the vector version and returns the first entry.
636 /// It returns true if the vector version returns true AND there
637 /// is at least one entry in the vector. No check is made for there
638 /// there being more than one entry in the vector.
639
640 vector<T> vals;
641 bool ret = GetCalib(namepath, vals);
642 if(vals.empty()) return true;
643 val = vals[0];
644
645 return ret;
646}
647
648//-------------
649// GetGeom (map)
650//-------------
651template<class T>
652bool JEventLoop::GetGeom(string namepath, map<string,T> &vals)
653{
654 /// Get the JGeometry object from JApplication for the run number of
655 /// the current event and call its Get() method to get the constants.
656
657 // Note that we could do this by making "vals" a generic type T thus, combining
658 // this with the vector version below. However, doing this explicitly will make
659 // it easier for the user to understand how to call us.
660
661 vals.clear();
662
663 JGeometry *geom = GetJGeometry();
664 if(!geom){
665 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<665<<" "
<<"Unable to get JGeometry object for run "<<event.GetRunNumber()<<std::endl;
666 return true;
667 }
668
669 return geom->Get(namepath, vals);
670}
671
672//-------------
673// GetGeom (atomic)
674//-------------
675template<class T> bool JEventLoop::GetGeom(string namepath, T &val)
676{
677 /// Get the JCalibration object from JApplication for the run number of
678 /// the current event and call its Get() method to get the constants.
679
680 JGeometry *geom = GetJGeometry();
681 if(!geom){
682 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<682<<" "
<<"Unable to get JGeometry object for run "<<event.GetRunNumber()<<std::endl;
683 return true;
684 }
685
686 return geom->Get(namepath, val);
687}
688
689//-------------
690// SetRef
691//-------------
692template<class T>
693void JEventLoop::SetRef(T *t)
694{
695 pair<const char*, void*> p(typeid(T).name(), (void*)t);
696 user_refs.push_back(p);
697}
698
699//-------------
700// GetResource
701//-------------
702template<class T> bool JEventLoop::GetResource(string namepath, T vals, int event_number)
703{
704 JResourceManager *resource_manager = GetJResourceManager();
705 if(!resource_manager){
706 string mess = string("Unable to get the JResourceManager object (namepath=\"")+namepath+"\")";
707 throw JException(mess);
708 }
709
710 return resource_manager->Get(namepath, vals, event_number);
711}
712
713//-------------
714// GetRef
715//-------------
716template<class T>
717T* JEventLoop::GetRef(void)
718{
719 /// Get a user-defined reference (a pointer)
720 for(unsigned int i=0; i<user_refs.size(); i++){
721 if(user_refs[i].first == typeid(T).name()) return (T*)user_refs[i].second;
722 }
723
724 return NULL__null;
725}
726
727//-------------
728// GetRefsT
729//-------------
730template<class T>
731vector<T*> JEventLoop::GetRefsT(void)
732{
733 vector<T*> refs;
734 for(unsigned int i=0; i<user_refs.size(); i++){
735 if(user_refs[i].first == typeid(T).name()){
736 refs.push_back((T*)user_refs[i].second);
737 }
738 }
739
740 return refs;
741}
742
743//-------------
744// RemoveRef
745//-------------
746template<class T>
747void JEventLoop::RemoveRef(T *t)
748{
749 vector<pair<const char*, void*> >::iterator iter;
750 for(iter=user_refs.begin(); iter!= user_refs.end(); iter++){
751 if(iter->second == (void*)t){
752 user_refs.erase(iter);
753 return;
754 }
755 }
756 _DBG_std::cerr<<"/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JEventLoop.h"
<<":"<<756<<" "
<<" Attempt to remove user reference not in event loop!" << std::endl;
757}
758
759
760#endif //__CINT__ __CLING__
761
762} // Close JANA namespace
763
764
765
766#endif // _JEventLoop_
767

/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/bits/stl_iterator.h

1// Iterators -*- C++ -*-
2
3// Copyright (C) 2001-2013 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1994
28 * Hewlett-Packard Company
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Hewlett-Packard Company makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
37 *
38 *
39 * Copyright (c) 1996-1998
40 * Silicon Graphics Computer Systems, Inc.
41 *
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Silicon Graphics makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
49 */
50
51/** @file bits/stl_iterator.h
52 * This is an internal header file, included by other library headers.
53 * Do not attempt to use it directly. @headername{iterator}
54 *
55 * This file implements reverse_iterator, back_insert_iterator,
56 * front_insert_iterator, insert_iterator, __normal_iterator, and their
57 * supporting functions and overloaded operators.
58 */
59
60#ifndef _STL_ITERATOR_H1
61#define _STL_ITERATOR_H1 1
62
63#include <bits/cpp_type_traits.h>
64#include <ext/type_traits.h>
65#include <bits/move.h>
66
67namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
68{
69_GLIBCXX_BEGIN_NAMESPACE_VERSION
70
71 /**
72 * @addtogroup iterators
73 * @{
74 */
75
76 // 24.4.1 Reverse iterators
77 /**
78 * Bidirectional and random access iterators have corresponding reverse
79 * %iterator adaptors that iterate through the data structure in the
80 * opposite direction. They have the same signatures as the corresponding
81 * iterators. The fundamental relation between a reverse %iterator and its
82 * corresponding %iterator @c i is established by the identity:
83 * @code
84 * &*(reverse_iterator(i)) == &*(i - 1)
85 * @endcode
86 *
87 * <em>This mapping is dictated by the fact that while there is always a
88 * pointer past the end of an array, there might not be a valid pointer
89 * before the beginning of an array.</em> [24.4.1]/1,2
90 *
91 * Reverse iterators can be tricky and surprising at first. Their
92 * semantics make sense, however, and the trickiness is a side effect of
93 * the requirement that the iterators must be safe.
94 */
95 template<typename _Iterator>
96 class reverse_iterator
97 : public iterator<typename iterator_traits<_Iterator>::iterator_category,
98 typename iterator_traits<_Iterator>::value_type,
99 typename iterator_traits<_Iterator>::difference_type,
100 typename iterator_traits<_Iterator>::pointer,
101 typename iterator_traits<_Iterator>::reference>
102 {
103 protected:
104 _Iterator current;
105
106 typedef iterator_traits<_Iterator> __traits_type;
107
108 public:
109 typedef _Iterator iterator_type;
110 typedef typename __traits_type::difference_type difference_type;
111 typedef typename __traits_type::pointer pointer;
112 typedef typename __traits_type::reference reference;
113
114 /**
115 * The default constructor value-initializes member @p current.
116 * If it is a pointer, that means it is zero-initialized.
117 */
118 // _GLIBCXX_RESOLVE_LIB_DEFECTS
119 // 235 No specification of default ctor for reverse_iterator
120 reverse_iterator() : current() { }
121
122 /**
123 * This %iterator will move in the opposite direction that @p x does.
124 */
125 explicit
126 reverse_iterator(iterator_type __x) : current(__x) { }
127
128 /**
129 * The copy constructor is normal.
130 */
131 reverse_iterator(const reverse_iterator& __x)
132 : current(__x.current) { }
133
134 /**
135 * A %reverse_iterator across other types can be copied if the
136 * underlying %iterator can be converted to the type of @c current.
137 */
138 template<typename _Iter>
139 reverse_iterator(const reverse_iterator<_Iter>& __x)
140 : current(__x.base()) { }
141
142 /**
143 * @return @c current, the %iterator used for underlying work.
144 */
145 iterator_type
146 base() const
147 { return current; }
148
149 /**
150 * @return A reference to the value at @c --current
151 *
152 * This requires that @c --current is dereferenceable.
153 *
154 * @warning This implementation requires that for an iterator of the
155 * underlying iterator type, @c x, a reference obtained by
156 * @c *x remains valid after @c x has been modified or
157 * destroyed. This is a bug: http://gcc.gnu.org/PR51823
158 */
159 reference
160 operator*() const
161 {
162 _Iterator __tmp = current;
163 return *--__tmp;
164 }
165
166 /**
167 * @return A pointer to the value at @c --current
168 *
169 * This requires that @c --current is dereferenceable.
170 */
171 pointer
172 operator->() const
173 { return &(operator*()); }
174
175 /**
176 * @return @c *this
177 *
178 * Decrements the underlying iterator.
179 */
180 reverse_iterator&
181 operator++()
182 {
183 --current;
184 return *this;
185 }
186
187 /**
188 * @return The original value of @c *this
189 *
190 * Decrements the underlying iterator.
191 */
192 reverse_iterator
193 operator++(int)
194 {
195 reverse_iterator __tmp = *this;
196 --current;
197 return __tmp;
198 }
199
200 /**
201 * @return @c *this
202 *
203 * Increments the underlying iterator.
204 */
205 reverse_iterator&
206 operator--()
207 {
208 ++current;
209 return *this;
210 }
211
212 /**
213 * @return A reverse_iterator with the previous value of @c *this
214 *
215 * Increments the underlying iterator.
216 */
217 reverse_iterator
218 operator--(int)
219 {
220 reverse_iterator __tmp = *this;
221 ++current;
222 return __tmp;
223 }
224
225 /**
226 * @return A reverse_iterator that refers to @c current - @a __n
227 *
228 * The underlying iterator must be a Random Access Iterator.
229 */
230 reverse_iterator
231 operator+(difference_type __n) const
232 { return reverse_iterator(current - __n); }
233
234 /**
235 * @return *this
236 *
237 * Moves the underlying iterator backwards @a __n steps.
238 * The underlying iterator must be a Random Access Iterator.
239 */
240 reverse_iterator&
241 operator+=(difference_type __n)
242 {
243 current -= __n;
244 return *this;
245 }
246
247 /**
248 * @return A reverse_iterator that refers to @c current - @a __n
249 *
250 * The underlying iterator must be a Random Access Iterator.
251 */
252 reverse_iterator
253 operator-(difference_type __n) const
254 { return reverse_iterator(current + __n); }
255
256 /**
257 * @return *this
258 *
259 * Moves the underlying iterator forwards @a __n steps.
260 * The underlying iterator must be a Random Access Iterator.
261 */
262 reverse_iterator&
263 operator-=(difference_type __n)
264 {
265 current += __n;
266 return *this;
267 }
268
269 /**
270 * @return The value at @c current - @a __n - 1
271 *
272 * The underlying iterator must be a Random Access Iterator.
273 */
274 reference
275 operator[](difference_type __n) const
276 { return *(*this + __n); }
277 };
278
279 //@{
280 /**
281 * @param __x A %reverse_iterator.
282 * @param __y A %reverse_iterator.
283 * @return A simple bool.
284 *
285 * Reverse iterators forward many operations to their underlying base()
286 * iterators. Others are implemented in terms of one another.
287 *
288 */
289 template<typename _Iterator>
290 inline bool
291 operator==(const reverse_iterator<_Iterator>& __x,
292 const reverse_iterator<_Iterator>& __y)
293 { return __x.base() == __y.base(); }
294
295 template<typename _Iterator>
296 inline bool
297 operator<(const reverse_iterator<_Iterator>& __x,
298 const reverse_iterator<_Iterator>& __y)
299 { return __y.base() < __x.base(); }
300
301 template<typename _Iterator>
302 inline bool
303 operator!=(const reverse_iterator<_Iterator>& __x,
304 const reverse_iterator<_Iterator>& __y)
305 { return !(__x == __y); }
306
307 template<typename _Iterator>
308 inline bool
309 operator>(const reverse_iterator<_Iterator>& __x,
310 const reverse_iterator<_Iterator>& __y)
311 { return __y < __x; }
312
313 template<typename _Iterator>
314 inline bool
315 operator<=(const reverse_iterator<_Iterator>& __x,
316 const reverse_iterator<_Iterator>& __y)
317 { return !(__y < __x); }
318
319 template<typename _Iterator>
320 inline bool
321 operator>=(const reverse_iterator<_Iterator>& __x,
322 const reverse_iterator<_Iterator>& __y)
323 { return !(__x < __y); }
324
325 template<typename _Iterator>
326 inline typename reverse_iterator<_Iterator>::difference_type
327 operator-(const reverse_iterator<_Iterator>& __x,
328 const reverse_iterator<_Iterator>& __y)
329 { return __y.base() - __x.base(); }
330
331 template<typename _Iterator>
332 inline reverse_iterator<_Iterator>
333 operator+(typename reverse_iterator<_Iterator>::difference_type __n,
334 const reverse_iterator<_Iterator>& __x)
335 { return reverse_iterator<_Iterator>(__x.base() - __n); }
336
337 // _GLIBCXX_RESOLVE_LIB_DEFECTS
338 // DR 280. Comparison of reverse_iterator to const reverse_iterator.
339 template<typename _IteratorL, typename _IteratorR>
340 inline bool
341 operator==(const reverse_iterator<_IteratorL>& __x,
342 const reverse_iterator<_IteratorR>& __y)
343 { return __x.base() == __y.base(); }
344
345 template<typename _IteratorL, typename _IteratorR>
346 inline bool
347 operator<(const reverse_iterator<_IteratorL>& __x,
348 const reverse_iterator<_IteratorR>& __y)
349 { return __y.base() < __x.base(); }
350
351 template<typename _IteratorL, typename _IteratorR>
352 inline bool
353 operator!=(const reverse_iterator<_IteratorL>& __x,
354 const reverse_iterator<_IteratorR>& __y)
355 { return !(__x == __y); }
356
357 template<typename _IteratorL, typename _IteratorR>
358 inline bool
359 operator>(const reverse_iterator<_IteratorL>& __x,
360 const reverse_iterator<_IteratorR>& __y)
361 { return __y < __x; }
362
363 template<typename _IteratorL, typename _IteratorR>
364 inline bool
365 operator<=(const reverse_iterator<_IteratorL>& __x,
366 const reverse_iterator<_IteratorR>& __y)
367 { return !(__y < __x); }
368
369 template<typename _IteratorL, typename _IteratorR>
370 inline bool
371 operator>=(const reverse_iterator<_IteratorL>& __x,
372 const reverse_iterator<_IteratorR>& __y)
373 { return !(__x < __y); }
374
375 template<typename _IteratorL, typename _IteratorR>
376#if __cplusplus201103L >= 201103L
377 // DR 685.
378 inline auto
379 operator-(const reverse_iterator<_IteratorL>& __x,
380 const reverse_iterator<_IteratorR>& __y)
381 -> decltype(__y.base() - __x.base())
382#else
383 inline typename reverse_iterator<_IteratorL>::difference_type
384 operator-(const reverse_iterator<_IteratorL>& __x,
385 const reverse_iterator<_IteratorR>& __y)
386#endif
387 { return __y.base() - __x.base(); }
388 //@}
389
390 // 24.4.2.2.1 back_insert_iterator
391 /**
392 * @brief Turns assignment into insertion.
393 *
394 * These are output iterators, constructed from a container-of-T.
395 * Assigning a T to the iterator appends it to the container using
396 * push_back.
397 *
398 * Tip: Using the back_inserter function to create these iterators can
399 * save typing.
400 */
401 template<typename _Container>
402 class back_insert_iterator
403 : public iterator<output_iterator_tag, void, void, void, void>
404 {
405 protected:
406 _Container* container;
407
408 public:
409 /// A nested typedef for the type of whatever container you used.
410 typedef _Container container_type;
411
412 /// The only way to create this %iterator is with a container.
413 explicit
414 back_insert_iterator(_Container& __x) : container(&__x) { }
415
416 /**
417 * @param __value An instance of whatever type
418 * container_type::const_reference is; presumably a
419 * reference-to-const T for container<T>.
420 * @return This %iterator, for chained operations.
421 *
422 * This kind of %iterator doesn't really have a @a position in the
423 * container (you can think of the position as being permanently at
424 * the end, if you like). Assigning a value to the %iterator will
425 * always append the value to the end of the container.
426 */
427#if __cplusplus201103L < 201103L
428 back_insert_iterator&
429 operator=(typename _Container::const_reference __value)
430 {
431 container->push_back(__value);
432 return *this;
433 }
434#else
435 back_insert_iterator&
436 operator=(const typename _Container::value_type& __value)
437 {
438 container->push_back(__value);
439 return *this;
440 }
441
442 back_insert_iterator&
443 operator=(typename _Container::value_type&& __value)
444 {
445 container->push_back(std::move(__value));
446 return *this;
447 }
448#endif
449
450 /// Simply returns *this.
451 back_insert_iterator&
452 operator*()
453 { return *this; }
454
455 /// Simply returns *this. (This %iterator does not @a move.)
456 back_insert_iterator&
457 operator++()
458 { return *this; }
459
460 /// Simply returns *this. (This %iterator does not @a move.)
461 back_insert_iterator
462 operator++(int)
463 { return *this; }
464 };
465
466 /**
467 * @param __x A container of arbitrary type.
468 * @return An instance of back_insert_iterator working on @p __x.
469 *
470 * This wrapper function helps in creating back_insert_iterator instances.
471 * Typing the name of the %iterator requires knowing the precise full
472 * type of the container, which can be tedious and impedes generic
473 * programming. Using this function lets you take advantage of automatic
474 * template parameter deduction, making the compiler match the correct
475 * types for you.
476 */
477 template<typename _Container>
478 inline back_insert_iterator<_Container>
479 back_inserter(_Container& __x)
480 { return back_insert_iterator<_Container>(__x); }
481
482 /**
483 * @brief Turns assignment into insertion.
484 *
485 * These are output iterators, constructed from a container-of-T.
486 * Assigning a T to the iterator prepends it to the container using
487 * push_front.
488 *
489 * Tip: Using the front_inserter function to create these iterators can
490 * save typing.
491 */
492 template<typename _Container>
493 class front_insert_iterator
494 : public iterator<output_iterator_tag, void, void, void, void>
495 {
496 protected:
497 _Container* container;
498
499 public:
500 /// A nested typedef for the type of whatever container you used.
501 typedef _Container container_type;
502
503 /// The only way to create this %iterator is with a container.
504 explicit front_insert_iterator(_Container& __x) : container(&__x) { }
505
506 /**
507 * @param __value An instance of whatever type
508 * container_type::const_reference is; presumably a
509 * reference-to-const T for container<T>.
510 * @return This %iterator, for chained operations.
511 *
512 * This kind of %iterator doesn't really have a @a position in the
513 * container (you can think of the position as being permanently at
514 * the front, if you like). Assigning a value to the %iterator will
515 * always prepend the value to the front of the container.
516 */
517#if __cplusplus201103L < 201103L
518 front_insert_iterator&
519 operator=(typename _Container::const_reference __value)
520 {
521 container->push_front(__value);
522 return *this;
523 }
524#else
525 front_insert_iterator&
526 operator=(const typename _Container::value_type& __value)
527 {
528 container->push_front(__value);
529 return *this;
530 }
531
532 front_insert_iterator&
533 operator=(typename _Container::value_type&& __value)
534 {
535 container->push_front(std::move(__value));
536 return *this;
537 }
538#endif
539
540 /// Simply returns *this.
541 front_insert_iterator&
542 operator*()
543 { return *this; }
544
545 /// Simply returns *this. (This %iterator does not @a move.)
546 front_insert_iterator&
547 operator++()
548 { return *this; }
549
550 /// Simply returns *this. (This %iterator does not @a move.)
551 front_insert_iterator
552 operator++(int)
553 { return *this; }
554 };
555
556 /**
557 * @param __x A container of arbitrary type.
558 * @return An instance of front_insert_iterator working on @p x.
559 *
560 * This wrapper function helps in creating front_insert_iterator instances.
561 * Typing the name of the %iterator requires knowing the precise full
562 * type of the container, which can be tedious and impedes generic
563 * programming. Using this function lets you take advantage of automatic
564 * template parameter deduction, making the compiler match the correct
565 * types for you.
566 */
567 template<typename _Container>
568 inline front_insert_iterator<_Container>
569 front_inserter(_Container& __x)
570 { return front_insert_iterator<_Container>(__x); }
571
572 /**
573 * @brief Turns assignment into insertion.
574 *
575 * These are output iterators, constructed from a container-of-T.
576 * Assigning a T to the iterator inserts it in the container at the
577 * %iterator's position, rather than overwriting the value at that
578 * position.
579 *
580 * (Sequences will actually insert a @e copy of the value before the
581 * %iterator's position.)
582 *
583 * Tip: Using the inserter function to create these iterators can
584 * save typing.
585 */
586 template<typename _Container>
587 class insert_iterator
588 : public iterator<output_iterator_tag, void, void, void, void>
589 {
590 protected:
591 _Container* container;
592 typename _Container::iterator iter;
593
594 public:
595 /// A nested typedef for the type of whatever container you used.
596 typedef _Container container_type;
597
598 /**
599 * The only way to create this %iterator is with a container and an
600 * initial position (a normal %iterator into the container).
601 */
602 insert_iterator(_Container& __x, typename _Container::iterator __i)
603 : container(&__x), iter(__i) {}
604
605 /**
606 * @param __value An instance of whatever type
607 * container_type::const_reference is; presumably a
608 * reference-to-const T for container<T>.
609 * @return This %iterator, for chained operations.
610 *
611 * This kind of %iterator maintains its own position in the
612 * container. Assigning a value to the %iterator will insert the
613 * value into the container at the place before the %iterator.
614 *
615 * The position is maintained such that subsequent assignments will
616 * insert values immediately after one another. For example,
617 * @code
618 * // vector v contains A and Z
619 *
620 * insert_iterator i (v, ++v.begin());
621 * i = 1;
622 * i = 2;
623 * i = 3;
624 *
625 * // vector v contains A, 1, 2, 3, and Z
626 * @endcode
627 */
628#if __cplusplus201103L < 201103L
629 insert_iterator&
630 operator=(typename _Container::const_reference __value)
631 {
632 iter = container->insert(iter, __value);
633 ++iter;
634 return *this;
635 }
636#else
637 insert_iterator&
638 operator=(const typename _Container::value_type& __value)
639 {
640 iter = container->insert(iter, __value);
641 ++iter;
642 return *this;
643 }
644
645 insert_iterator&
646 operator=(typename _Container::value_type&& __value)
647 {
648 iter = container->insert(iter, std::move(__value));
649 ++iter;
650 return *this;
651 }
652#endif
653
654 /// Simply returns *this.
655 insert_iterator&
656 operator*()
657 { return *this; }
658
659 /// Simply returns *this. (This %iterator does not @a move.)
660 insert_iterator&
661 operator++()
662 { return *this; }
663
664 /// Simply returns *this. (This %iterator does not @a move.)
665 insert_iterator&
666 operator++(int)
667 { return *this; }
668 };
669
670 /**
671 * @param __x A container of arbitrary type.
672 * @return An instance of insert_iterator working on @p __x.
673 *
674 * This wrapper function helps in creating insert_iterator instances.
675 * Typing the name of the %iterator requires knowing the precise full
676 * type of the container, which can be tedious and impedes generic
677 * programming. Using this function lets you take advantage of automatic
678 * template parameter deduction, making the compiler match the correct
679 * types for you.
680 */
681 template<typename _Container, typename _Iterator>
682 inline insert_iterator<_Container>
683 inserter(_Container& __x, _Iterator __i)
684 {
685 return insert_iterator<_Container>(__x,
686 typename _Container::iterator(__i));
687 }
688
689 // @} group iterators
690
691_GLIBCXX_END_NAMESPACE_VERSION
692} // namespace
693
694namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
695{
696_GLIBCXX_BEGIN_NAMESPACE_VERSION
697
698 // This iterator adapter is @a normal in the sense that it does not
699 // change the semantics of any of the operators of its iterator
700 // parameter. Its primary purpose is to convert an iterator that is
701 // not a class, e.g. a pointer, into an iterator that is a class.
702 // The _Container parameter exists solely so that different containers
703 // using this template can instantiate different types, even if the
704 // _Iterator parameter is the same.
705 using std::iterator_traits;
706 using std::iterator;
707 template<typename _Iterator, typename _Container>
708 class __normal_iterator
709 {
710 protected:
711 _Iterator _M_current;
712
713 typedef iterator_traits<_Iterator> __traits_type;
714
715 public:
716 typedef _Iterator iterator_type;
717 typedef typename __traits_type::iterator_category iterator_category;
718 typedef typename __traits_type::value_type value_type;
719 typedef typename __traits_type::difference_type difference_type;
720 typedef typename __traits_type::reference reference;
721 typedef typename __traits_type::pointer pointer;
722
723 _GLIBCXX_CONSTEXPRconstexpr __normal_iterator() : _M_current(_Iterator()) { }
724
725 explicit
726 __normal_iterator(const _Iterator& __i) : _M_current(__i) { }
727
728 // Allow iterator to const_iterator conversion
729 template<typename _Iter>
730 __normal_iterator(const __normal_iterator<_Iter,
731 typename __enable_if<
732 (std::__are_same<_Iter, typename _Container::pointer>::__value),
733 _Container>::__type>& __i)
734 : _M_current(__i.base()) { }
735
736 // Forward iterator requirements
737 reference
738 operator*() const
739 { return *_M_current; }
740
741 pointer
742 operator->() const
743 { return _M_current; }
744
745 __normal_iterator&
746 operator++()
747 {
748 ++_M_current;
749 return *this;
750 }
751
752 __normal_iterator
753 operator++(int)
754 { return __normal_iterator(_M_current++); }
755
756 // Bidirectional iterator requirements
757 __normal_iterator&
758 operator--()
759 {
760 --_M_current;
761 return *this;
762 }
763
764 __normal_iterator
765 operator--(int)
766 { return __normal_iterator(_M_current--); }
767
768 // Random access iterator requirements
769 reference
770 operator[](const difference_type& __n) const
771 { return _M_current[__n]; }
772
773 __normal_iterator&
774 operator+=(const difference_type& __n)
775 { _M_current += __n; return *this; }
776
777 __normal_iterator
778 operator+(const difference_type& __n) const
779 { return __normal_iterator(_M_current + __n); }
780
781 __normal_iterator&
782 operator-=(const difference_type& __n)
783 { _M_current -= __n; return *this; }
784
785 __normal_iterator
786 operator-(const difference_type& __n) const
787 { return __normal_iterator(_M_current - __n); }
788
789 const _Iterator&
790 base() const
791 { return _M_current; }
792 };
793
794 // Note: In what follows, the left- and right-hand-side iterators are
795 // allowed to vary in types (conceptually in cv-qualification) so that
796 // comparison between cv-qualified and non-cv-qualified iterators be
797 // valid. However, the greedy and unfriendly operators in std::rel_ops
798 // will make overload resolution ambiguous (when in scope) if we don't
799 // provide overloads whose operands are of the same type. Can someone
800 // remind me what generic programming is about? -- Gaby
801
802 // Forward iterator requirements
803 template<typename _IteratorL, typename _IteratorR, typename _Container>
804 inline bool
805 operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
806 const __normal_iterator<_IteratorR, _Container>& __rhs)
807 { return __lhs.base() == __rhs.base(); }
808
809 template<typename _Iterator, typename _Container>
810 inline bool
811 operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
812 const __normal_iterator<_Iterator, _Container>& __rhs)
813 { return __lhs.base() == __rhs.base(); }
814
815 template<typename _IteratorL, typename _IteratorR, typename _Container>
816 inline bool
817 operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs,
818 const __normal_iterator<_IteratorR, _Container>& __rhs)
819 { return __lhs.base() != __rhs.base(); }
820
821 template<typename _Iterator, typename _Container>
822 inline bool
823 operator!=(const __normal_iterator<_Iterator, _Container>& __lhs,
824 const __normal_iterator<_Iterator, _Container>& __rhs)
825 { return __lhs.base() != __rhs.base(); }
18
Assuming the condition is true
19
Returning the value 1, which participates in a condition later
826
827 // Random access iterator requirements
828 template<typename _IteratorL, typename _IteratorR, typename _Container>
829 inline bool
830 operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
831 const __normal_iterator<_IteratorR, _Container>& __rhs)
832 { return __lhs.base() < __rhs.base(); }
833
834 template<typename _Iterator, typename _Container>
835 inline bool
836 operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
837 const __normal_iterator<_Iterator, _Container>& __rhs)
838 { return __lhs.base() < __rhs.base(); }
839
840 template<typename _IteratorL, typename _IteratorR, typename _Container>
841 inline bool
842 operator>(const __normal_iterator<_IteratorL, _Container>& __lhs,
843 const __normal_iterator<_IteratorR, _Container>& __rhs)
844 { return __lhs.base() > __rhs.base(); }
845
846 template<typename _Iterator, typename _Container>
847 inline bool
848 operator>(const __normal_iterator<_Iterator, _Container>& __lhs,
849 const __normal_iterator<_Iterator, _Container>& __rhs)
850 { return __lhs.base() > __rhs.base(); }
851
852 template<typename _IteratorL, typename _IteratorR, typename _Container>
853 inline bool
854 operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs,
855 const __normal_iterator<_IteratorR, _Container>& __rhs)
856 { return __lhs.base() <= __rhs.base(); }
857
858 template<typename _Iterator, typename _Container>
859 inline bool
860 operator<=(const __normal_iterator<_Iterator, _Container>& __lhs,
861 const __normal_iterator<_Iterator, _Container>& __rhs)
862 { return __lhs.base() <= __rhs.base(); }
863
864 template<typename _IteratorL, typename _IteratorR, typename _Container>
865 inline bool
866 operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs,
867 const __normal_iterator<_IteratorR, _Container>& __rhs)
868 { return __lhs.base() >= __rhs.base(); }
869
870 template<typename _Iterator, typename _Container>
871 inline bool
872 operator>=(const __normal_iterator<_Iterator, _Container>& __lhs,
873 const __normal_iterator<_Iterator, _Container>& __rhs)
874 { return __lhs.base() >= __rhs.base(); }
875
876 // _GLIBCXX_RESOLVE_LIB_DEFECTS
877 // According to the resolution of DR179 not only the various comparison
878 // operators but also operator- must accept mixed iterator/const_iterator
879 // parameters.
880 template<typename _IteratorL, typename _IteratorR, typename _Container>
881#if __cplusplus201103L >= 201103L
882 // DR 685.
883 inline auto
884 operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
885 const __normal_iterator<_IteratorR, _Container>& __rhs)
886 -> decltype(__lhs.base() - __rhs.base())
887#else
888 inline typename __normal_iterator<_IteratorL, _Container>::difference_type
889 operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
890 const __normal_iterator<_IteratorR, _Container>& __rhs)
891#endif
892 { return __lhs.base() - __rhs.base(); }
893
894 template<typename _Iterator, typename _Container>
895 inline typename __normal_iterator<_Iterator, _Container>::difference_type
896 operator-(const __normal_iterator<_Iterator, _Container>& __lhs,
897 const __normal_iterator<_Iterator, _Container>& __rhs)
898 { return __lhs.base() - __rhs.base(); }
899
900 template<typename _Iterator, typename _Container>
901 inline __normal_iterator<_Iterator, _Container>
902 operator+(typename __normal_iterator<_Iterator, _Container>::difference_type
903 __n, const __normal_iterator<_Iterator, _Container>& __i)
904 { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); }
905
906_GLIBCXX_END_NAMESPACE_VERSION
907} // namespace
908
909#if __cplusplus201103L >= 201103L
910
911namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
912{
913_GLIBCXX_BEGIN_NAMESPACE_VERSION
914
915 /**
916 * @addtogroup iterators
917 * @{
918 */
919
920 // 24.4.3 Move iterators
921 /**
922 * Class template move_iterator is an iterator adapter with the same
923 * behavior as the underlying iterator except that its dereference
924 * operator implicitly converts the value returned by the underlying
925 * iterator's dereference operator to an rvalue reference. Some
926 * generic algorithms can be called with move iterators to replace
927 * copying with moving.
928 */
929 template<typename _Iterator>
930 class move_iterator
931 {
932 protected:
933 _Iterator _M_current;
934
935 typedef iterator_traits<_Iterator> __traits_type;
936
937 public:
938 typedef _Iterator iterator_type;
939 typedef typename __traits_type::iterator_category iterator_category;
940 typedef typename __traits_type::value_type value_type;
941 typedef typename __traits_type::difference_type difference_type;
942 // NB: DR 680.
943 typedef _Iterator pointer;
944 typedef value_type&& reference;
945
946 move_iterator()
947 : _M_current() { }
948
949 explicit
950 move_iterator(iterator_type __i)
951 : _M_current(__i) { }
952
953 template<typename _Iter>
954 move_iterator(const move_iterator<_Iter>& __i)
955 : _M_current(__i.base()) { }
956
957 iterator_type
958 base() const
959 { return _M_current; }
960
961 reference
962 operator*() const
963 { return std::move(*_M_current); }
964
965 pointer
966 operator->() const
967 { return _M_current; }
968
969 move_iterator&
970 operator++()
971 {
972 ++_M_current;
973 return *this;
974 }
975
976 move_iterator
977 operator++(int)
978 {
979 move_iterator __tmp = *this;
980 ++_M_current;
981 return __tmp;
982 }
983
984 move_iterator&
985 operator--()
986 {
987 --_M_current;
988 return *this;
989 }
990
991 move_iterator
992 operator--(int)
993 {
994 move_iterator __tmp = *this;
995 --_M_current;
996 return __tmp;
997 }
998
999 move_iterator
1000 operator+(difference_type __n) const
1001 { return move_iterator(_M_current + __n); }
1002
1003 move_iterator&
1004 operator+=(difference_type __n)
1005 {
1006 _M_current += __n;
1007 return *this;
1008 }
1009
1010 move_iterator
1011 operator-(difference_type __n) const
1012 { return move_iterator(_M_current - __n); }
1013
1014 move_iterator&
1015 operator-=(difference_type __n)
1016 {
1017 _M_current -= __n;
1018 return *this;
1019 }
1020
1021 reference
1022 operator[](difference_type __n) const
1023 { return std::move(_M_current[__n]); }
1024 };
1025
1026 // Note: See __normal_iterator operators note from Gaby to understand
1027 // why there are always 2 versions for most of the move_iterator
1028 // operators.
1029 template<typename _IteratorL, typename _IteratorR>
1030 inline bool
1031 operator==(const move_iterator<_IteratorL>& __x,
1032 const move_iterator<_IteratorR>& __y)
1033 { return __x.base() == __y.base(); }
1034
1035 template<typename _Iterator>
1036 inline bool
1037 operator==(const move_iterator<_Iterator>& __x,
1038 const move_iterator<_Iterator>& __y)
1039 { return __x.base() == __y.base(); }
1040
1041 template<typename _IteratorL, typename _IteratorR>
1042 inline bool
1043 operator!=(const move_iterator<_IteratorL>& __x,
1044 const move_iterator<_IteratorR>& __y)
1045 { return !(__x == __y); }
1046
1047 template<typename _Iterator>
1048 inline bool
1049 operator!=(const move_iterator<_Iterator>& __x,
1050 const move_iterator<_Iterator>& __y)
1051 { return !(__x == __y); }
1052
1053 template<typename _IteratorL, typename _IteratorR>
1054 inline bool
1055 operator<(const move_iterator<_IteratorL>& __x,
1056 const move_iterator<_IteratorR>& __y)
1057 { return __x.base() < __y.base(); }
1058
1059 template<typename _Iterator>
1060 inline bool
1061 operator<(const move_iterator<_Iterator>& __x,
1062 const move_iterator<_Iterator>& __y)
1063 { return __x.base() < __y.base(); }
1064
1065 template<typename _IteratorL, typename _IteratorR>
1066 inline bool
1067 operator<=(const move_iterator<_IteratorL>& __x,
1068 const move_iterator<_IteratorR>& __y)
1069 { return !(__y < __x); }
1070
1071 template<typename _Iterator>
1072 inline bool
1073 operator<=(const move_iterator<_Iterator>& __x,
1074 const move_iterator<_Iterator>& __y)
1075 { return !(__y < __x); }
1076
1077 template<typename _IteratorL, typename _IteratorR>
1078 inline bool
1079 operator>(const move_iterator<_IteratorL>& __x,
1080 const move_iterator<_IteratorR>& __y)
1081 { return __y < __x; }
1082
1083 template<typename _Iterator>
1084 inline bool
1085 operator>(const move_iterator<_Iterator>& __x,
1086 const move_iterator<_Iterator>& __y)
1087 { return __y < __x; }
1088
1089 template<typename _IteratorL, typename _IteratorR>
1090 inline bool
1091 operator>=(const move_iterator<_IteratorL>& __x,
1092 const move_iterator<_IteratorR>& __y)
1093 { return !(__x < __y); }
1094
1095 template<typename _Iterator>
1096 inline bool
1097 operator>=(const move_iterator<_Iterator>& __x,
1098 const move_iterator<_Iterator>& __y)
1099 { return !(__x < __y); }
1100
1101 // DR 685.
1102 template<typename _IteratorL, typename _IteratorR>
1103 inline auto
1104 operator-(const move_iterator<_IteratorL>& __x,
1105 const move_iterator<_IteratorR>& __y)
1106 -> decltype(__x.base() - __y.base())
1107 { return __x.base() - __y.base(); }
1108
1109 template<typename _Iterator>
1110 inline auto
1111 operator-(const move_iterator<_Iterator>& __x,
1112 const move_iterator<_Iterator>& __y)
1113 -> decltype(__x.base() - __y.base())
1114 { return __x.base() - __y.base(); }
1115
1116 template<typename _Iterator>
1117 inline move_iterator<_Iterator>
1118 operator+(typename move_iterator<_Iterator>::difference_type __n,
1119 const move_iterator<_Iterator>& __x)
1120 { return __x + __n; }
1121
1122 template<typename _Iterator>
1123 inline move_iterator<_Iterator>
1124 make_move_iterator(_Iterator __i)
1125 { return move_iterator<_Iterator>(__i); }
1126
1127 template<typename _Iterator, typename _ReturnType
1128 = typename conditional<__move_if_noexcept_cond
1129 <typename iterator_traits<_Iterator>::value_type>::value,
1130 _Iterator, move_iterator<_Iterator>>::type>
1131 inline _ReturnType
1132 __make_move_if_noexcept_iterator(_Iterator __i)
1133 { return _ReturnType(__i); }
1134
1135 // @} group iterators
1136
1137_GLIBCXX_END_NAMESPACE_VERSION
1138} // namespace
1139
1140#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) std::make_move_iterator(_Iter)
1141#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) \
1142 std::__make_move_if_noexcept_iterator(_Iter)
1143#else
1144#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter)std::make_move_iterator(_Iter) (_Iter)
1145#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter)std::__make_move_if_noexcept_iterator(_Iter) (_Iter)
1146#endif // C++11
1147
1148#endif