Bug Summary

File:libraries/TRACKING/DTrackCandidate_factory_CDC.cc
Location:line 589, column 16
Description:Dereference of null pointer

Annotated Source Code

1// $Id$
2//
3// File: DTrackCandidate_factory_CDC.cc
4// Created: Thu Sep 6 14:47:48 EDT 2007
5// Creator: davidl (on Darwin Amelia.local 8.10.1 i386)
6//
7
8#include <algorithm>
9using namespace std;
10
11#include <DVector2.h>
12#include <CDC/DCDCTrackHit.h>
13#include "DHelicalFit.h"
14#include <HDGEOMETRY/DGeometry.h>
15#include <HDGEOMETRY/DMagneticFieldMap.h>
16
17#define BeamRMS1.0 1.0
18#define EPS1e-3 1e-3
19
20#include "DTrackCandidate_factory_CDC.h"
21
22#define TWO(c)(0x1u << (c)) (0x1u << (c))
23#define MASK(c)((unsigned int)(-1)) / ((0x1u << ((0x1u << (c))))
+ 1u)
((unsigned int)(-1)) / (TWO(TWO(c))(0x1u << ((0x1u << (c)))) + 1u)
24#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)
)
25
26inline int bitcount (unsigned int n) {
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
36
37
38class DVector3_with_perp:public DVector3
39{
40 public:
41 DVector3_with_perp():DVector3(){CalcPerp();}
42 DVector3_with_perp(double x, double y, double z):DVector3(x,y,z){CalcPerp();}
43 double CalcPerp(void){
44 perp = Perp();
45 return perp;
46 }
47 double perp;
48};
49
50inline bool SortIntersections(const DVector3_with_perp &a,const DVector3_with_perp &b){
51 if (a.perp<b.perp) return true;
52 return false;
53}
54
55inline bool CDCSortByRdecreasing(DTrackCandidate_factory_CDC::DCDCTrkHit* const &hit1, DTrackCandidate_factory_CDC::DCDCTrkHit* const &hit2) {
56 // use the ring number to sort by R(decreasing) and then straw(increasing)
57 if(hit1->hit->wire->ring == hit2->hit->wire->ring){
58 return hit1->hit->wire->straw < hit2->hit->wire->straw;
59 }
60 return hit1->hit->wire->ring > hit2->hit->wire->ring;
61}
62inline bool CDCSortByRincreasing(DTrackCandidate_factory_CDC::DCDCTrkHit* const &hit1, DTrackCandidate_factory_CDC::DCDCTrkHit* const &hit2) {
63 // use the ring number to sort by R
64 return hit1->hit->wire->ring < hit2->hit->wire->ring;
65}
66inline bool CDCSortByZincreasing(DTrackCandidate_factory_CDC::DCDCTrkHit* const &hit1, DTrackCandidate_factory_CDC::DCDCTrkHit* const &hit2) {
67 // use the z_stereo position to sort
68 return hit1->z_stereo < hit2->z_stereo;
69}
70inline bool CDCSortByStereoPhiincreasing(DTrackCandidate_factory_CDC::DCDCTrkHit* const &hit1, DTrackCandidate_factory_CDC::DCDCTrkHit* const &hit2) {
71 // use the z_stereo position to sort
72 return hit1->phi_stereo < hit2->phi_stereo;
73}
74
75//------------------
76// init
77//------------------
78jerror_t DTrackCandidate_factory_CDC::init(void)
79{
80 MAX_ALLOWED_CDC_HITS = 10000;
81 MAX_SUBSEED_STRAW_DIFF = 1;
82 MIN_SEED_HITS = 2;
83 MAX_SUBSEED_LINKED_HITS = 12;
84 MAX_RING_SUBSEED_HITS = 4;
85 MAX_HIT_DIST = 4.0; // cm
86 MAX_SEED_TIME_DIFF = 1000.0; // ns
87 MAX_CDC_MATCH_ANGLE = 20.0; // degrees
88
89 MAX_SEED_LINK_ANGLE = M_PI3.14159265358979323846/6.0*57.3; // degrees
90 TARGET_Z_MIN = 50.0;
91 TARGET_Z_MAX = 80.0;
92 TARGET_Z=65.0;
93 DEBUG_LEVEL = 0;
94
95 FILTER_SEEDS=false;
96
97 // Initialize cdchits_by_superlayer with empty vectors for each superlayer
98 vector<DCDCTrkHit*> mt;
99 for(int i=0; i<5; i++)cdchits_by_superlayer.push_back(mt);
100
101 // Set the layer numbers defining the superlayer boundaries
102 superlayer_boundaries.push_back( 4);
103 superlayer_boundaries.push_back(12);
104 superlayer_boundaries.push_back(16);
105 superlayer_boundaries.push_back(24);
106 superlayer_boundaries.push_back(28);
107
108 return NOERROR;
109}
110
111//------------------
112// brun
113//------------------
114jerror_t DTrackCandidate_factory_CDC::brun(JEventLoop *eventLoop, int runnumber)
115{
116 DApplication* dapp=dynamic_cast<DApplication*>(eventLoop->GetJApplication());
117 bfield = dapp->GetBfield();
118
119 // get the geometry
120 const DGeometry *geom = dapp->GetDGeometry(runnumber);
121
122 geom->GetTargetZ(TARGET_Z);
123 double zrange;
124 geom->GetTargetLength(zrange);
125 TARGET_Z_MIN=TARGET_Z-0.5*zrange;
126 TARGET_Z_MAX=TARGET_Z+0.5*zrange;
127
128
129 gPARMS->SetDefaultParameter("TRKFIND:MAX_ALLOWED_CDC_HITS", MAX_ALLOWED_CDC_HITS);
130 gPARMS->SetDefaultParameter("TRKFIND:MAX_SUBSEED_STRAW_DIFF", MAX_SUBSEED_STRAW_DIFF);
131 gPARMS->SetDefaultParameter("TRKFIND:MIN_SEED_HITS", MIN_SEED_HITS);
132 gPARMS->SetDefaultParameter("TRKFIND:MAX_SUBSEED_LINKED_HITS", MAX_SUBSEED_LINKED_HITS);
133 gPARMS->SetDefaultParameter("TRKFIND:MAX_RING_SUBSEED_HITS", MAX_RING_SUBSEED_HITS);
134 gPARMS->SetDefaultParameter("TRKFIND:MAX_HIT_DIST", MAX_HIT_DIST);
135 gPARMS->SetDefaultParameter("TRKFIND:MAX_SEED_TIME_DIFF", MAX_SEED_TIME_DIFF);
136 gPARMS->SetDefaultParameter("TRKFIND:MAX_CDC_MATCH_ANGLE", MAX_CDC_MATCH_ANGLE);
137
138 gPARMS->SetDefaultParameter("TRKFIND:MAX_SEED_LINK_ANGLE", MAX_SEED_LINK_ANGLE);
139 gPARMS->SetDefaultParameter("TRKFIND:DEBUG_LEVEL", DEBUG_LEVEL);
140 gPARMS->SetDefaultParameter("TRKFIND:FILTER_SEEDS",FILTER_SEEDS);
141
142 MAX_HIT_DIST2 = MAX_HIT_DIST*MAX_HIT_DIST;
143
144 return NOERROR;
145}
146
147//------------------
148// erun
149//------------------
150jerror_t DTrackCandidate_factory_CDC::erun(void)
151{
152 return NOERROR;
153}
154
155//------------------
156// fini
157//------------------
158jerror_t DTrackCandidate_factory_CDC::fini(void)
159{
160 for(unsigned int i=0; i<cdctrkhits.size(); i++)delete cdctrkhits[i];
161 return NOERROR;
162}
163
164//------------------
165// evnt
166//------------------
167jerror_t DTrackCandidate_factory_CDC::evnt(JEventLoop *loop, int eventnumber)
168{
169 // Get CDC hits
170 unsigned int numcdchits=0;
171 if (GetCDCHits(loop,numcdchits)!=NOERROR){
172 return RESOURCE_UNAVAILABLE;
173 }
174
175 // Find all seeds in all 3 axial superlayers
176 vector<DCDCSeed> seeds_sl5;
177 vector<DCDCSeed> seeds_sl3;
178 vector<DCDCSeed> seeds_sl1;
179 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
179<<" "
<<"========= SL5 =========="<<endl;
180 FindSeeds(cdchits_by_superlayer[5-1], seeds_sl5);
181 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
181<<" "
<<"========= SL3 =========="<<endl;
182 FindSeeds(cdchits_by_superlayer[3-1], seeds_sl3);
183 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
183<<" "
<<"========= SL1 =========="<<endl;
184 FindSeeds(cdchits_by_superlayer[1-1], seeds_sl1);
185
186 // Link seeds using average phi of seed hits
187 vector<DCDCSeed> seeds_tmp, seeds_tmpSL5,seeds_tmpSL3_SL5,seeds;
188 LinkSeeds(seeds_sl5, seeds_sl3, seeds_tmp, MAX_SUBSEED_LINKED_HITS);
189
190 // Put aside the seeds that only have hits in SL5
191 for (unsigned int i=0;i<seeds_tmp.size();i++){
192 unsigned int max_ind=seeds_tmp[i].hits.size()-1;
193 if (seeds_tmp[i].hits[max_ind]->hit->wire->ring>24){
194 seeds_tmpSL5.push_back(seeds_tmp[i]);
195 }
196 else{
197 seeds_tmpSL3_SL5.push_back(seeds_tmp[i]);
198 }
199 }
200
201 // Link seeds between SL1 and SL3+SL5
202 LinkSeeds(seeds_tmpSL3_SL5, seeds_sl1, seeds, 2*MAX_SUBSEED_LINKED_HITS);
203
204 // Insert the SL5 seeds into the full list of seeds
205 seeds.insert(seeds.begin(),seeds_tmpSL5.begin(),seeds_tmpSL5.end());
206
207 // Check to add lone hits in SL3 to seeds with only SL1 hits
208 PickupUnmatched(seeds);
209
210 // Drop seeds containing hits from only a single axial superlayer besides SL1
211 DropIncompleteSeeds(seeds);
212
213 if (seeds.size()>0){
214 // Create vectors to store bit pattern of hits used by the seeds
215 for (unsigned int i=0;i<seeds.size();i++){
216 seeds[i].HitBitPattern.clear();
217 seeds[i].HitBitPattern.resize(numcdchits/(8*sizeof(unsigned int))+1);
218 }
219
220 // Fit linked seeds to circles
221 for(unsigned int i=0; i<seeds.size(); i++){
222 if(DEBUG_LEVEL>5)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
222<<" "
<<"-- Starting fit for seed "<<i<<" Nhits="<<seeds[i].hits.size()<<" phi_avg="<<seeds[i].phi_avg<<endl;
223 seeds[i].valid = FitCircle(seeds[i]);
224 }
225
226 // Filter out duplicates of seeds by clearing their "valid" flags
227 FilterCloneSeeds(seeds);
228
229 // Extend seeds into stereo layers and do fit to find z and theta
230 for(unsigned int i=0; i<seeds.size(); i++){
231 DCDCSeed &seed = seeds[i];
232 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
232<<" "
<<"----- Seed "<<i<<" ------"<<endl;
233 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
233<<" "
<<"seed.fit.phi="<<seed.fit.phi<<endl;
234 if(!seed.valid)continue;
235
236 // Add stereo hits to seed
237 AddStereoHits(cdchits_by_superlayer[2-1], seed);
238
239 // If there are hits in the first axial layers but no hits in the first
240 // stereo layers, then this is unlikely to be a valid (fittable)
241 // candidate...
242 unsigned int first_stereo_count=seed.stereo_hits.size();
243 if (first_stereo_count==0 && seed.hits[0]->hit->wire->ring<5){
244 seed.valid=false;
245 continue;
246 }
247
248 // Go on to the next set of stereo layers
249 AddStereoHits(cdchits_by_superlayer[4-1], seed);
250
251 // If no stereo hits were found for this seed, then
252 // we can't fit it.
253 if(seed.stereo_hits.size()==0){
254 seed.valid=false;
255 continue;
256 }
257
258 if (FindThetaZRegression(seed)!=NOERROR){
259 // If the linear regression doesn't work try the histogramming method
260 // Fit stereo hits to get theta and vertex z position
261 FindThetaZ(seed);
262 if(!seed.valid){
263 //continue;
264
265 // Assume that the track came from one end or the other
266 // of the target and use a point in one of the stereo
267 // layers to estimate tanl
268 if (seed.z_vertex>TARGET_Z_MAX)
269 seed.z_vertex=TARGET_Z_MAX;
270 else
271 seed.z_vertex=TARGET_Z_MIN;
272 double x=seed.stereo_hits[0].x_stereo;
273 double y=seed.stereo_hits[0].y_stereo;
274 double ratio=sqrt(x*x+y*y)/2./seed.fit.r0;
275 if (ratio<1.){
276 double tanl=(seed.stereo_hits[0].z_stereo-seed.z_vertex)/
277 (2.*seed.fit.r0*asin(ratio));
278 seed.theta=M_PI_21.57079632679489661923-atan(tanl);
279 }
280
281 }
282 }
283 }
284
285 if (FILTER_SEEDS){
286 //Look for seeds that share hits and mark a seed as invalid if it shares more
287 //than a certain fraction (to be determined) of hits with another seed and the
288 //chisq/df from the circle fit is worse than that of the other fit by a
289 //certain amount
290 unsigned int numwords=seeds[0].HitBitPattern.size();
291 for(unsigned int i=0; i<seeds.size()-1; i++){
292 if (seeds[i].valid){
293 for (unsigned int j=i+1;j<seeds.size();j++){
294 if (seeds[j].valid){
295 int numcommon=0;
296 for (unsigned int k=0;k<numwords;k++){
297 numcommon
298 +=bitcount(seeds[i].HitBitPattern[k]&seeds[j].HitBitPattern[k]);
299 }
300 double hitratio=double(numcommon)/
301 double(seeds[i].hits.size()+seeds[i].stereo_hits.size());
302 double chisq_nu_1=seeds[i].fit.chisq/seeds[i].fit.ndof;
303 double chisq_nu_2=seeds[j].fit.chisq/seeds[j].fit.ndof;
304 if (hitratio>0.9 || (hitratio>0.5 && fabs(chisq_nu_1-chisq_nu_2)>1)){
305 if (chisq_nu_1 > chisq_nu_2) seeds[i].valid=false;
306 else seeds[j].valid=false;
307 }
308 }
309 }
310 }
311 }
312 }
313
314 // Put the good seeds in the list of cdc track candidates
315 for(unsigned int i=0; i<seeds.size(); i++){
316 DCDCSeed seed = seeds[i];
317 if (seed.valid){
318 // The following is from a fit of ratio of thrown to reconstructed
319 // transverse momentum vs. theta for the 1400A field
320 //double par[] = {0.984463, 0.150759, -0.414933, 0.257472, -0.055801};
321 //double theta = seed.theta;
322 //double ff = par[0]+theta*(par[1]+theta*(par[2]+theta*(par[3]+theta*par[4])));
323
324 DVector3 pos, mom;
325 GetPositionAndMomentum(seed,pos,mom);
326
327 //Make a track candidate from results
328 DTrackCandidate *can = new DTrackCandidate;
329
330 can->setPosition(pos);
331 can->setMomentum(mom);
332 //can->setCharge(seed.q);
333 can->setCharge(seed.fit.q);
334
335 for (unsigned int n=0;n<seed.hits.size();n++){
336 const DCDCTrackHit *cdchit=(seed.hits[n])->hit;
337 can->used_cdc_indexes.push_back(seed.hits[n]->index);
338 can->AddAssociatedObject(cdchit);
339 }
340 for (unsigned int n=0;n<seed.stereo_hits.size();n++){
341 const DCDCTrackHit *cdchit=(seed.stereo_hits[n]).hit;
342 can->used_cdc_indexes.push_back((seed.stereo_hits[n]).index);
343 can->AddAssociatedObject(cdchit);
344 }
345
346
347 //can->q = can->charge();
348 //can->phi = mom.Phi();
349 //can->theta = mom.Theta();
350 //can->p_trans = mom.Pt();
351 //can->p = mom.Mag();
352 //can->z_vertex = pos.Z();
353 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
353<<" "
<<"Final Candidate parameters: p="<<mom.Mag()<<" theta="<<mom.Theta()<<" phi="<<mom.Phi()<<" z="<<pos.Z()<<endl;
354
355 _data.push_back(can);
356 }
357 }
358 }
359
360 return NOERROR;
361}
362
363//------------------
364// GetCDCHits
365//------------------
366jerror_t DTrackCandidate_factory_CDC::GetCDCHits(JEventLoop *loop,
367 unsigned int &numhits)
368{
369 // Delete old hits
370 for(unsigned int i=0; i<cdctrkhits.size(); i++)delete cdctrkhits[i];
371 cdctrkhits.clear();
372 for(unsigned int i=0; i<cdchits_by_superlayer.size(); i++)cdchits_by_superlayer[i].clear();
373
374
375 // Get the "raw" hits. These already have the wire associated with them.
376 vector<const DCDCTrackHit*> cdctrackhits;
377 loop->Get(cdctrackhits);
378 numhits=cdctrackhits.size();
379
380 // If there are no hits, then bail now
381 if(cdctrackhits.size()==0)return RESOURCE_UNAVAILABLE;
382
383 // If there are too many hits, bail with a warning message
384 if(cdctrackhits.size()>MAX_ALLOWED_CDC_HITS){
385 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
385<<" "
<<"Too many hits in CDC ("<<cdctrackhits.size()<<", max="<<MAX_ALLOWED_CDC_HITS<<")! Track finding in CDC bypassed for event "<<loop->GetJEvent().GetEventNumber()<<endl;
386 cdctrackhits.clear();
387 return UNRECOVERABLE_ERROR;
388 }
389
390 // Create DCDCTrkHit objects out of these.
391 int oldwire = -1;
392 for(unsigned int i=0; i<cdctrackhits.size(); i++){
393 // Add to "master" list
394 // ONLY FIRST HIT OF A WIRE
395 int newwire = cdctrackhits[i]->wire->ring*1000 + cdctrackhits[i]->wire->straw;
396 if (newwire!=oldwire){
397
398 oldwire = newwire;
399
400 // Add to "master" list
401 DCDCTrkHit *cdctrkhit = new DCDCTrkHit;
402 cdctrkhit->index=i;
403 cdctrkhit->hit = cdctrackhits[i];
404 cdctrkhit->flags = cdctrkhit->hit->is_stereo==false ? NONE:IS_STEREO;
405 cdctrkhit->flags |= NOISE; // (see below)
406
407 cdctrkhits.push_back(cdctrkhit);
408
409 // Sort into list of hits by superlayer
410#if 1
411 for(unsigned int j=0; j<superlayer_boundaries.size(); j++){
412 if(cdctrkhit->hit->wire->ring<=superlayer_boundaries[j]){
413 cdchits_by_superlayer[j].push_back(cdctrkhit);
414 break;
415 }
416 }
417#else
418 if(cdctrkhit->hit->wire->ring<=4)cdchits_by_superlayer[0].push_back(cdctrkhit);
419 else if(cdctrkhit->hit->wire->ring<= 12)cdchits_by_superlayer[1].push_back(cdctrkhit);
420 else if(cdctrkhit->hit->wire->ring<=16)cdchits_by_superlayer[2].push_back(cdctrkhit);
421 else if(cdctrkhit->hit->wire->ring<=24)cdchits_by_superlayer[3].push_back(cdctrkhit);
422 else if(cdctrkhit->hit->wire->ring<=28)cdchits_by_superlayer[4].push_back(cdctrkhit);
423#endif
424 }
425 }
426
427 // Sort the individual superlayer lists by decreasing values of R
428 for(unsigned int i=0; i<cdchits_by_superlayer.size(); i++){
429 sort(cdchits_by_superlayer[i].begin(), cdchits_by_superlayer[i].end(), CDCSortByRdecreasing);
430 }
431
432 // Filter out noise hits. All hits are initially flagged as "noise".
433 // Hits with a neighbor within MAX_HIT_DIST have their noise flags cleared.
434 for(unsigned int i=0; i<cdctrkhits.size(); i++){ // cut above should ensure cdctrkhits.size() is at least 1
435 DCDCTrkHit *trkhit1 = cdctrkhits[i];
436 if(!(trkhit1->flags & NOISE))continue; // this hit already not marked for noise
437 for(unsigned int j=0; j<cdctrkhits.size(); j++){
438 if(j==i)continue;
439 double d2 = trkhit1->Dist2(cdctrkhits[j]);
440 if(d2<9.0*MAX_HIT_DIST2){
441 trkhit1->flags &= ~NOISE;
442 cdctrkhits[j]->flags &= ~NOISE;
443 break;
444 }// if
445 }// j
446 }// i
447 return NOERROR;
448}
449
450//------------------
451// FindSeeds
452//------------------
453void DTrackCandidate_factory_CDC::FindSeeds(vector<DCDCTrkHit*> &hits, vector<DCDCSeed> &seeds)
454{
455 // Sort through hits ring by ring to find sub-seeds from neighboring wires
456 // in the same ring. What we want is a list of sub-seeds for each ring.
457 // Each sub-seed is a list of adjacent (or nearly adjacent) hits. Note
458 // that hits are ordered by ring, then straw. We ignore the boundary in
459 // straw number for now which will cause some sub-seeds to be listed as
460 // 2 separate ones. These will be recombined later.
461 DCDCSeed subseed;
462 vector<DCDCSeed > subseeds;
463 vector<vector<DCDCSeed > > rings;
464 int last_ring = -1;
465 for(unsigned int i=0; i<hits.size(); i++){
1
Loop condition is false. Execution continues on line 495
466 DCDCTrkHit *trkhit = hits[i];
467
468 // Clear USED, IN_SEED, IN_LINE, IN_TRACK flags for all these hits
469 trkhit->flags &= ~(USED|IN_SEED|IN_LINE|IN_TRACK);
470
471 //if(trkhit->flags & NOISE)continue;
472
473 // Check if ring number has changed.
474 if(trkhit->hit->wire->ring != last_ring){
475 if(subseed.hits.size()!=0)subseeds.push_back(subseed);
476 if(subseeds.size()!=0)rings.push_back(subseeds);
477 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
477<<" "
<<" subseed hits:"<<subseed.hits.size()<<" subseeds:"<<subseeds.size()<<endl;
478 subseeds.clear();
479 subseed.hits.clear();
480 subseed.hits.push_back(trkhit);
481 subseed.linked=false;
482 last_ring = trkhit->hit->wire->ring;
483 continue;
484 }
485
486 // Check if this hit is a neighbor of the last hit added to the subseed
487 if((unsigned int)abs(subseed.hits[subseed.hits.size()-1]->hit->wire->straw - trkhit->hit->wire->straw)>MAX_SUBSEED_STRAW_DIFF){
488 if(subseed.hits.size()!=0)subseeds.push_back(subseed);
489 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
489<<" "
<<" subseed hits:"<<subseed.hits.size()<<endl;
490 subseed.hits.clear();
491 subseed.linked=false;
492 }
493 subseed.hits.push_back(trkhit);
494 }
495 if(subseed.hits.size()!=0)subseeds.push_back(subseed);
2
Taking false branch
496 if(subseeds.size()!=0)rings.push_back(subseeds);
3
Taking false branch
497 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
497<<" "
<<" subseed hits:"<<subseed.hits.size()<<" subseeds:"<<subseeds.size()<<endl;
4
Taking false branch
498 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
498<<" "
<<"rings: "<<rings.size()<<endl;
5
Taking false branch
499
500 // If we have no "rings", then there must be no seeds. Bail now
501 if(rings.size()==0)return;
6
Taking false branch
502
503 // Loop over rings
504 for(ringiter ring =rings.begin(); ring!=rings.end(); ring++){
7
Loop condition is true. Entering loop body
9
Loop condition is true. Entering loop body
11
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
505 vector<DCDCSeed> &subseeds = *ring;
506 ringiter next_ring = ring;
507 next_ring++;
508
509 // Loop over subseeds of this ring
510 for(unsigned int j=0; j<subseeds.size(); j++){
8
Loop condition is false. Execution continues on line 504
10
Loop condition is false. Execution continues on line 504
12
Loop condition is false. Execution continues on line 504
14
Loop condition is true. Entering loop body
511 if(subseeds[j].linked)continue;
15
Taking false branch
512 if(subseeds[j].hits.size()>MAX_RING_SUBSEED_HITS){
16
Taking false branch
513 if(DEBUG_LEVEL>4)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
513<<" "
<<"rejecting subseed for having too many hits in a single layer ("<<subseeds[j].hits.size()<<" max="<<MAX_RING_SUBSEED_HITS<<")"<<endl;
514 continue;
515 }
516
517 // This subseed was never used. Start a new seed
518 vector<DCDCSeed*> parent;
519 parent.push_back(&subseeds[j]);
520 LinkSubSeeds(parent, next_ring, rings.end(), seeds);
17
Calling 'LinkSubSeeds'
521 }
522 }
523
524 // Mark all seeds as valid
525 for(unsigned int i=0; i<seeds.size(); i++){
526 seeds[i].valid = true;
527 }
528}
529
530//------------------
531// LinkSubSeeds
532//------------------
533void DTrackCandidate_factory_CDC::LinkSubSeeds(vector<DCDCSeed*> &parent, ringiter ring, ringiter ringend, vector<DCDCSeed> &seeds)
534{
535 /// Combine subseeds from layers in a single superlayer into seeds.
536 ///
537 /// This a a re-entrant routine (i.e. it calls itself recursively). Upon
538 /// entry, <i>parent</i> contains a list of pointers to all of the subseeds
539 /// from the rings outside of <i>ring</i> that are to be combined into
540 /// a seed. This will search through all subseeds of <i>ring</i> and if
541 /// any are found that can extend the parent, a copy of parent is made,
542 /// the current subseed of this ring is added to it, and then it is
543 /// passed on to another call to this routine. If no matches are found
544 /// (which will necessarily be the case for the inner most layer), then
545 /// the subseeds in <i>parent</i> will be combined into a single seed and
546 /// that added to <i>seeds</i>.
547
548 // Make sure parent has at least one subseed
549 if(parent.size()==0){
18
Taking false branch
550 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
550<<" "
<<"parent has no subseeds!!"<<endl;
551 return;
552 }
553
554 // Set flag to keep track of whether this is the end of the seed or not
555 bool seed_extended = false;
556 if(ring!=ringend){
19
Taking false branch
557
558 // Last subseed in parent list is the one we need to compare to
559 DCDCSeed *parent_subseed = parent[parent.size()-1];
560 double r_parent = parent_subseed->hits[0]->hit->wire->origin.Perp();
561
562 // Loop over subseeds in this ring
563 vector<DCDCSeed> &subseeds = (*ring);
564 ring++; // increment ring iterator to point to next level down in case we recall ouself below
565
566 for(unsigned int i=0; i<subseeds.size(); i++){
567 // Find the difference between this subseed's distance from the beamline
568 // and the parent's.
569 double dr = r_parent - subseeds[i].hits[0]->hit->wire->origin.Perp();
570
571 // Check if this subseed is close enough to the parent's to extend it
572 if(parent_subseed->MinDist2(subseeds[i])<(dr*dr+MAX_HIT_DIST2)){
573 vector<DCDCSeed*> myparent = parent;
574 myparent.push_back(&subseeds[i]);
575 subseeds[i].linked = true;
576 LinkSubSeeds(myparent, ring, ringend, seeds);
577 seed_extended = true;
578 }
579 }
580 }
581
582 // Check if this is the end of the line.
583 if(!seed_extended){
20
Taking true branch
584 // This is the end of this seed. Combine the subseeds into a single
585 // seed and add it to the list.
586 DCDCSeed seed;
587 seed.hits.clear();
588 for(unsigned int i=0; i<parent.size(); i++){
21
Loop condition is true. Entering loop body
589 seed.Merge(*parent[i]);
22
Dereference of null pointer
590 }
591 if(seed.hits.size()>=MIN_SEED_HITS){
592 seeds.push_back(seed);
593 }else{
594 if(DEBUG_LEVEL>1)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
594<<" "
<<"rejecting seed due to too few hits (have "<<seed.hits.size()<<" need "<<MIN_SEED_HITS<<")"<<endl;
595 }
596 }
597}
598
599//------------------
600// LinkSeeds
601//------------------
602void DTrackCandidate_factory_CDC::LinkSeeds(vector<DCDCSeed> &in_seeds1, vector<DCDCSeed> &in_seeds2, vector<DCDCSeed> &seeds, unsigned int max_linked_hits)
603{
604 /// Loop over the two input sets of seeds and compare the phi angles of
605 /// their first and last hits. The closest combination is checked to see
606 /// if we should combine them into a new a new seed. Any seeds from either
607 /// list that are not linked, but have enough hits to be a full seed in and
608 /// of themselves will be added to the <i>seeds</i> list.
609 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
609<<" "
<<"Linking seeds: Num seeds in list 1:"<<in_seeds1.size()<<" Num seeds in list 2:"<<in_seeds2.size()<<endl;
610
611 // Clear all "linked" flags
612 for(unsigned int i=0; i< in_seeds1.size(); i++)in_seeds1[i].linked=false;
613 for(unsigned int i=0; i< in_seeds2.size(); i++)in_seeds2[i].linked=false;
614
615 for(unsigned int i=0; i< in_seeds1.size(); i++){
616 vector<DCDCTrkHit*> &hits1 = in_seeds1[i].hits;
617 if(DEBUG_LEVEL>5)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
617<<" "
<<"hits1.size()="<<hits1.size()<<endl;
618 if(hits1.size()<1)continue;
619
620 for(unsigned int j=0; j< in_seeds2.size(); j++){
621 vector<DCDCTrkHit*> &hits2 = in_seeds2[j].hits;
622 if(DEBUG_LEVEL>5)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
622<<" "
<<" hits2.size()="<<hits2.size()<<endl;
623 if(hits2.size()<1)continue;
624
625 // Find the hits from the seeds that are closest in R
626 const DCDCWire *wire1a = hits1[0]->hit->wire;
627 const DCDCWire *wire1b = hits1[hits1.size()-1]->hit->wire;
628 const DCDCWire *wire2a = hits2[0]->hit->wire;
629 const DCDCWire *wire2b = hits2[hits2.size()-1]->hit->wire;
630 const DVector3 *pos1, *pos2;
631 if(wire1a->ring > wire2a->ring){
632 // seed1 is outside seed2
633 pos1 = &(wire1a->ring > wire1b->ring ? wire1b:wire1a)->origin;
634 pos2 = &(wire2a->ring < wire2b->ring ? wire2b:wire2a)->origin;
635 }else{
636 // seed2 is outside seed1
637 pos1 = &(wire1a->ring < wire1b->ring ? wire1b:wire1a)->origin;
638 pos2 = &(wire2a->ring > wire2b->ring ? wire2b:wire2a)->origin;
639 }
640
641 // Compare the phi values of the first and last points of the two seeds
642 // to see if they are close enough to link.
643 double dphi = fabs(pos1->Phi() - pos2->Phi());
644 while(dphi>M_PI3.14159265358979323846)dphi-=2.0*M_PI3.14159265358979323846;
645 if(fabs(dphi*57.3)<MAX_SEED_LINK_ANGLE){
646
647 DCDCSeed seed = in_seeds1[i];
648 seed.Merge(in_seeds2[j]);
649 seeds.push_back(seed);
650
651 // Mark all of the hits in the new, merged seed as USED. Some will
652 // already have the flag set by having been previously merged. The
653 // USED flag is used later when matching SL1 only seeds with stray
654 // hits in SL3.
655 for(unsigned int k=0; k<seed.hits.size(); k++){
656 seed.hits[k]->flags |= USED;
657 }
658
659 // OK, at this point we have linked the seeds and we *may* want to
660 // to set thier "linked" flags. The linked flags are really used
661 // to decide later if the partial seed should be promoted to
662 // a full seed. The idea here is to only flag the seed as "linked"
663 // if the link is strong, otherwise leaved it marked as unlinked
664 // so it has the option of becoming another track candidate at
665 // the next level. Note that even if we set a linked flag here,
666 // the partial seed can still be linked with other partials in
667 // this loop.
668 //
669 // The criteria for a strong link are:
670 // 1. the number of hits in the partner's partial seed is not
671 // greater than max_linked_hits (which is passed to us as an
672 // argument)
673 // 2. The minimum distance between the partial seeds' ends is less
674 // than 3*MAX_HIT_DIST in the phi direction.
675
676 // Find distance between seeds' ends
677 double dr = fabs(pos1->Perp() - pos2->Perp());
678 DVector3 d = *pos1 - *pos2;
679 double dist_phi2 = d.Perp2() - dr*dr;
680
681 if(dist_phi2 < 9.0*MAX_HIT_DIST2){
682
683 // Mark the seeds has having been linked. Here we do something
684 // a little funny. We only mark a seed as linked if the other
685 // seed doesn't have too many hits. This is because we can get
686 // "super seeds" from a single superlayer made from many hits,
687 // often due to crossing tracks.
688 if(hits1.size()<=max_linked_hits)in_seeds2[j].linked = true;
689 if(hits2.size()<=max_linked_hits)in_seeds1[i].linked = true;
690 }else{
691 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
691<<" "
<<" not marking seeds as linked (dist_phi="<<sqrt(dist_phi2)<<" cm > "<<sqrt(9.0*MAX_HIT_DIST2)<<" cm)"<<endl;
692 }
693 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
693<<" "
<<" linked seeds "<<i<<" ("<<hits1.size()<<" hits) and "<<j<<" ("<<hits2.size()<<" hits) dist_phi="<<sqrt(dist_phi2)<<endl;
694 }else{
695 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
695<<" "
<<" rejected link between "<<i<<" and "<<j<<" due to avg. phi (fabs("<<in_seeds1[i].phi_avg*57.3<<" - "<<in_seeds2[j].phi_avg*57.3<<")>="<<MAX_SEED_LINK_ANGLE<<")"<<endl;
696 }
697 }
698 }
699
700 // Any seeds that weren't linked from either list should be promoted
701 // to full seeds.
702 for(unsigned int i=0; i< in_seeds1.size(); i++){
703 if(!in_seeds1[i].linked){
704 seeds.push_back(in_seeds1[i]);
705 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
705<<" "
<<"Promoting seed "<<i<<" from list 1"<<endl;
706 }
707 }
708 for(unsigned int i=0; i< in_seeds2.size(); i++){
709 if(!in_seeds2[i].linked){
710 seeds.push_back(in_seeds2[i]);
711 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
711<<" "
<<"Promoting seed "<<i<<" from list 2"<<endl;
712 }
713 }
714
715 // Calculate average time for all axial hits in each seed and set
716 // all seeds to a charge of +1
717 for(unsigned int i=0; i< seeds.size(); i++){
718 DCDCSeed &seed = seeds[i];
719 seed.tdrift_avg = 0.0;
720 unsigned int Nin_time=0;
721 for(unsigned int j=0; j<seed.hits.size(); j++){
722 double tdrift = seed.hits[j]->hit->tdrift;
723 if(tdrift>1000.0){
724 seed.hits[j]->flags |= OUT_OF_TIME;
725 continue;
726 }
727 seed.tdrift_avg += tdrift;
728 Nin_time++;
729 }
730 seed.tdrift_avg /= (double)Nin_time;
731 }
732}
733
734//------------------
735// FitCircle
736//------------------
737bool DTrackCandidate_factory_CDC::FitCircle(DCDCSeed &seed)
738{
739 /// Do a quick fit of the 2-D projection of the axial hits
740 /// in seed (seed should contain *only* axial hits) to a
741 /// circle. Determine the sign of the charge (and correspondingly
742 /// the initial phi angle) assuming that
743 /// the majority of hits come from the outgoing part of the
744 /// track. If the resulting circle passes within
745 /// MAX_HIT_DIST of more the majority of hits, then true
746 /// is returned indicating success. Otherwise, false is
747 /// returned indicating failure and that the seed should be
748 /// discarded.
749
750 // Loop over hits in seed and add them to the seed's DHelicalFit object
751 seed.fit.Clear();
752 for(unsigned int j=0; j<seed.hits.size(); j++){
753 unsigned int numbits=8*sizeof(unsigned int);
754 seed.HitBitPattern[seed.hits[j]->index/numbits]
755 |=0x1u<<seed.hits[j]->index%numbits;
756
757 if(seed.hits[j]->flags&OUT_OF_TIME)continue;
758
759 const DVector3 &pos = seed.hits[j]->hit->wire->origin;
760 seed.fit.AddHitXYZ(pos.X(), pos.Y(),pos.Z());
761 }
762
763 // Try and fit the circle using a Riemann fit. If
764 // it fails, try a basic fit with QuickFit.
765 if(seed.fit.FitCircleRiemann(TARGET_Z,BeamRMS1.0)!=NOERROR
766 /* || seed.fit.chisq>20*/
767 ){
768 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
768<<" "
<<"Riemann fit failed. Attempting regression fit..."<<endl;
769 if(seed.fit.FitCircle()!=NOERROR
770 /*|| seed.fit.chisq>20*/
771 ){
772 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
772<<" "
<<"Regression circle fit failed. Trying straight line."<<endl;
773 if(seed.fit.FitCircleStraightTrack()!=NOERROR){
774 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
774<<" "
<<"Trying straight line fit failed. Giving up."<<endl;
775 return false;
776 }
777 }else{
778 seed.fit.GuessChargeFromCircleFit(); // for Riemann fit
779 }
780 }else{
781 seed.fit.GuessChargeFromCircleFit(); // for regression fit
782 }
783
784 // Check if majority of hits are close to circle.
785 double x0 = seed.fit.x0;
786 double y0 = seed.fit.y0;
787 double r0 = seed.fit.r0;
788
789 unsigned int N=0;
790 for(unsigned int i=0; i<seed.hits.size(); i++){
791 if(seed.hits[i]->flags&OUT_OF_TIME){
792 if(DEBUG_LEVEL>6)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
792<<" "
<<"discarding out of time hit"<<endl;
793 continue;
794 }
795 double dx = seed.hits[i]->hit->wire->origin.X() - x0;
796 double dy = seed.hits[i]->hit->wire->origin.Y() - y0;
797 double d = sqrt(dx*dx + dy*dy);
798 if(DEBUG_LEVEL>15)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
798<<" "
<<"dist="<<d-r0<<endl;
799 if(fabs(d-r0)<=MAX_HIT_DIST)N++;
800 }
801
802 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
802<<" "
<<"Circle fit: Nhits="<<seed.fit.GetNhits()<<" p_trans="<<seed.fit.p_trans<<" q="<<seed.fit.q<<" N="<<N<<" phi="<<seed.fit.phi<<endl;
803 if(N<MIN_SEED_HITS){
804 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
804<<" "
<<"Rejected circle fit due to too few hits on track (N="<<N<<" MIN_SEED_HITS="<<MIN_SEED_HITS<<")"<<endl;
805 return false;
806 }
807
808 if(N<seed.hits.size()/2){
809 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
809<<" "
<<"Rejected circle fit due to minority of hits on track (N="<<N<<" seed.hits.size()/2="<<seed.hits.size()/2<<")"<<endl;
810 return false;
811 }
812 return true;
813}
814
815//------------------
816// PickupUnmatched
817//------------------
818void DTrackCandidate_factory_CDC::PickupUnmatched(vector<DCDCSeed> &seeds)
819{
820 /// Look for single hits in superlayers that did not have enough
821 /// neighbors to make seeds of their own, but could be part of
822 /// a seed made in another axial superlayer. This is mainly here
823 /// to address tracks that have a single hit in SL3 that is
824 /// otherwise discarded. Seeds with only hits in SL1 often
825 /// don't enough information to form a good candidate so we try
826 /// and pick up these single hits in order to get a good handle
827 /// on the candidate.
828
829 // Loop through seeds, looking for ones with only SL1 hits
830 for(unsigned int i=0; i<seeds.size(); i++){
831 if(!seeds[i].valid)continue;
832 vector<DCDCTrkHit*> &hits = seeds[i].hits;
833 if(hits.size()<1)continue;
834 bool has_non_SL1_hit = false;
835 for(unsigned int j=0; j<hits.size(); j++){
836 if(hits[j]->hit->wire->ring>superlayer_boundaries[0]){
837 has_non_SL1_hit = true;
838 break;
839 }
840 }
841 if(has_non_SL1_hit)continue;
842 if(DEBUG_LEVEL>1)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
842<<" "
<<"seed "<<i<<" has only SL1 hits. Looking for stray hits to match it with ..."<<endl;
843
844 // This seed must have only SL1 hits, look for unused SL3 hits
845 // at a phi angle consistent with the outermost hit.
846 bool added_hit = false;
847 const DCDCWire *sl1_wire = hits[hits.size()-1]->hit->wire;
848 for(unsigned int j=0; j<cdctrkhits.size(); j++){
849 DCDCTrkHit *sl3_hit = cdctrkhits[j];
850 if(sl3_hit->flags&USED)continue;
851 if(sl3_hit->hit->wire->ring<=superlayer_boundaries[1])continue;
852 if(sl3_hit->hit->wire->ring>superlayer_boundaries[2])continue;
853 double a = sl1_wire->origin.Angle(sl3_hit->hit->wire->origin);
854 if(fabs(a)<MAX_CDC_MATCH_ANGLE/57.3){
855 sl3_hit->flags |= USED;
856 hits.push_back(sl3_hit);
857 added_hit = true;
858 if(DEBUG_LEVEL>1)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
858<<" "
<<"Adding stray SL3 hit to SL1 seed a="<<a*57.3<<" flags="<<sl3_hit->flags<<" ring="<<sl3_hit->hit->wire->ring<<endl;
859 }
860 }
861
862 if(added_hit){
863 if(DEBUG_LEVEL>1)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
863<<" "
<<" found SL3 CDC hit to add to seed "<<i<<endl;
864 continue; // We found at least one SL3 hit that was added to the seed
865 }
866
867 }
868}
869
870//------------------
871// DropIncompleteSeeds
872//------------------
873void DTrackCandidate_factory_CDC::DropIncompleteSeeds(vector<DCDCSeed> &seeds)
874{
875 /// Look for seeds that have hits only in SL3 or only in SL5 and drop them.
876
877 int iSL1_lo = 1;
878 int iSL1_hi = superlayer_boundaries[0];
879 int iSL3_lo = superlayer_boundaries[1]+1;
880 int iSL3_hi = superlayer_boundaries[2];
881 int iSL5_lo = superlayer_boundaries[3]+1;
882 int iSL5_hi = superlayer_boundaries[3];
883
884 // Loop through seeds, looking for ones with only SL1 hits
885 for(unsigned int i=0; i<seeds.size(); i++){
886 if(!seeds[i].valid)continue;
887 vector<DCDCTrkHit*> &hits = seeds[i].hits;
888 if(hits.size()<1)continue;
889 bool has_SL1_hit = false;
890 bool has_SL3_hit = false;
891 bool has_SL5_hit = false;
892 for(unsigned int j=0; j<hits.size(); j++){
893 int ring = hits[j]->hit->wire->ring;
894 if(ring<iSL1_lo || ring>iSL1_hi)has_SL1_hit = true;
895 if(ring<iSL3_lo || ring>iSL3_hi)has_SL3_hit = true;
896 if(ring<iSL5_lo || ring>iSL5_hi)has_SL5_hit = true;
897 if(has_SL1_hit)break;
898 }
899 if(has_SL1_hit)continue;
900 if(has_SL3_hit && has_SL5_hit)continue;
901
902 // Seed contains hits only from superlayer 3 or only from superlayer 5
903 // Flag the seed as invalid so it is ignored later
904 seeds[i].valid = false;
905 if(DEBUG_LEVEL>1)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
905<<" "
<<"Dropping seed "<<i<<": hits in oly SL3 or only SL5 (has_SL3_hit="<<has_SL3_hit<<", has_SL5_hit="<<has_SL5_hit<<")"<<endl;
906 }
907}
908
909//------------------
910// FilterCloneSeeds
911//------------------
912void DTrackCandidate_factory_CDC::FilterCloneSeeds(vector<DCDCSeed> &seeds)
913{
914 /// Look for clones of seeds and flag all but one as not valid.
915 /// Two tracks are considered clones if their trajectories are
916 /// really close.
917
918 /// The "closeness" of the two trajectories is determined using
919 /// two methods, either of which can flag the two seeds as clones.
920 ///
921 /// For the first method, we use the "asymmetry" of the circle
922 /// centers. The asymmetry is defined as the distance between
923 /// the two circle's centers divided by the sum of the magnitudes
924 /// of the circle's centers relative to the origin. If this is below
925 /// some threshold (say 0.05) then the tracks are seeds are
926 /// considered clones.
927 ///
928 /// For the second method, we check the distance between the
929 /// trajectories at a point near the last hit and a point near
930 /// one of the middle hits of one of the seeds. Since all
931 /// seeds pass through the origin, this effectively gives 3
932 /// points on the circle(s). If the total sum of the distances
933 /// between these points and the other seed's track are less than
934 /// some small value, the two are considered clones. Note that
935 /// currently, the choice of "middle" hits is done simply by
936 /// looking at the N/2th hit. This may not actually be near the
937 /// middle of the R values so a more sophisticated algorithm
938 /// may need to be implemented later.
939
940 for(unsigned int i=0; i<seeds.size(); i++){
941 DCDCSeed &seed1 = seeds[i];
942 if(!seed1.valid)continue;
943
944 // Calculate point on seed1 closest to last(furthest out) hit on seed1
945 DVector2 r1(seed1.fit.x0, seed1.fit.y0);
946 const DVector3 &wire_pos1 = seed1.hits[seed1.hits.size()-1]->hit->wire->origin;
947 DVector2 alpha1(wire_pos1.X(), wire_pos1.Y());
948 alpha1 -= r1;
949 alpha1 *= r1.Mod()/alpha1.Mod();
950
951 // Calculate point on seed1 at about the midpoint hit on seed1
952 const DVector3 &wire_pos2 = seed1.hits[seed1.hits.size()/2]->hit->wire->origin;
953 DVector2 alpha2(wire_pos2.X(), wire_pos2.Y());
954 alpha2 -= r1;
955 alpha2 *= r1.Mod()/alpha2.Mod();
956
957 for(unsigned int j=i+1; j<seeds.size(); j++){
958 DCDCSeed &seed2 = seeds[j];
959 if(!seed2.valid)continue;
960
961 // Flag to indicate these are clones
962 bool are_clones = false;
963
964 // If the two circle fits are significantly different (i.e.
965 // their x0, y0 coordinates aren't close), then skip assume
966 // these seeds aren't duplicates.
967 DVector2 r2(seed2.fit.x0, seed2.fit.y0);
968 DVector2 dr = r1-r2;
969 double asym = dr.Mod()/(r1.Mod()+r2.Mod());
970 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
970<<" "
<<"asym="<<asym<<endl;
971 if(asym<0.05) are_clones = true;
972
973 if(!are_clones){
974 // Find total absolute distance from alpha1 and seed2 circle and
975 // alpha2 and seed2 circle.
976 DVector2 d1 = dr+alpha1;
977 DVector2 d2 = dr+alpha2;
978 double d = fabs(d1.Mod()-r2.Mod()) + fabs(d2.Mod() - r2.Mod());
979 if(d<1.5) are_clones = true;
980 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
980<<" "
<<"d="<<d<<endl;
981 }
982 // Check that the charges are the same
983 if (are_clones){
984 if (seed1.fit.q!=seed2.fit.q) are_clones=false;
985
986 }
987 // Remove a clone in necessary
988 if(are_clones){
989 // These seeds appear to be clones of one another. Mark one as not valid.
990
991 if(seed1.fit.chisq<=seed2.fit.chisq){
992 seed2.valid = false;
993 }else{
994 seed1.valid = false;
995 }
996
997 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
997<<" "
<<"Filtering clone circle seed (seed1.fit.chisq="<<seed1.fit.chisq<<" seed2.fit.chisq="<<seed2.fit.chisq<<endl;
998 }
999 }
1000 }
1001}
1002
1003//------------------
1004// AddStereoHits
1005//------------------
1006void DTrackCandidate_factory_CDC::AddStereoHits(vector<DCDCTrkHit*> &stereo_hits, DCDCSeed &seed)
1007{
1008 // To find the z coordinate, we look at the 2D projection of the
1009 // stereo wire and find the intersection point of that with the
1010 // circle found in FitSeed().
1011
1012 // Loop over stereo hits to find z-values for any that cross this circle
1013 for(unsigned int i=0; i<stereo_hits.size(); i++){
1014 DCDCTrkHit *trkhit = stereo_hits[i];
1015
1016 // Don't consider hits that are out of time with the seed
1017 if(fabs(trkhit->hit->tdrift-seed.tdrift_avg)>MAX_SEED_TIME_DIFF){
1018 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1018<<" "
<<"Out of time stereo hit: seed.tdrift_avg="<<seed.tdrift_avg<<" tdrift="<<trkhit->hit->tdrift<<endl;
1019 continue;
1020 }
1021
1022 // Calculate intersection points between circle and stereo wire
1023 const DCDCWire *wire = trkhit->hit->wire;
1024 DVector2 r1(wire->origin.X(), wire->origin.Y());
1025 DVector2 r2(wire->udir.X(), wire->udir.Y());
1026 DVector2 R(seed.fit.x0, seed.fit.y0);
1027 double r2_mod2 = r2.Mod2();
1028 if(r2_mod2<1.0E-10){
1029 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1029<<" "
<<"wire in CDC stereo hit list is not stereo!"<<endl;
1030 continue; // this must not be a stereo wire!
1031 }
1032
1033 double a = r2_mod2;
1034 double b = 2.0*r2*(r1-R);
1035 double c = r1.Mod2()-2.0*r1*R;
1036 double A = b*b - 4.0*a*c;
1037
1038 // Check that this wire intersects this circle
1039 if(A<0.0)continue; // line along wire does not intersect circle, ever.
1040
1041 // Calculate intersection points for two roots of alpha
1042 double B = sqrt(A);
1043 double alpha1 = (-b - B)/(2.0*a);
1044 double alpha2 = (-b + B)/(2.0*a);
1045
1046 if(DEBUG_LEVEL>15)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1046<<" "
<<"alpha1="<<alpha1<<" alpha2="<<alpha2<<endl;
1047
1048 // At this point we must decide which value of alpha to use. The
1049 // proper way would likely involve either trying both possibilities
1050 // and taking the one that gave the better chi-sq for a line fit
1051 // of phi vs. z or looking at the surrounding axial layers
1052 // and using the value which puts the hit closest to those.
1053 // For now, we just use the value closest to zero (i.e. closest to
1054 // the center of the wire).
1055 //double alpha = sqrt(r2_mod2)*(fabs(alpha1)<fabs(alpha2) ? alpha1:alpha2);
1056
1057 // Now we must convert the alpha value into a z-value. To do this,
1058 // we use the known theta angle of the wire. The distance along the
1059 // wire from the center in 3D is given by:
1060 //
1061 // s = alpha/sin(theta_wire)
1062 //
1063 // The z coordinate of the hit is given by:
1064 //
1065 // z = z1 + s*z2
1066 //
1067 // where z1 is the z coordinate of the center of the wire and z2
1068 // is the z component of the direction of the wire. i.e.
1069 //
1070 // z2 = cos(theta_wire)
1071 //
1072 // This means sin(theta_wire) = sqrt(1 - (z2)^2)
1073 //double z2 = wire->udir.Z();
1074 //double s = alpha/fabs(sin(wire->stereo));
1075 // The above code unnecessarily multiples and divides by sin(theta_wire)
1076 double s=(fabs(alpha1)<fabs(alpha2) ? alpha1:alpha2);
1077
1078 //if(DEBUG_LEVEL>3)_DBG_<<"alpha="<<alpha<<" s="<<s<<" ring="<<wire->ring<<" straw="<<wire->straw<<" stereo="<<wire->stereo<<endl;
1079 if(DEBUG_LEVEL>15)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1079<<" "
<<"s="<<s<<" ring="<<wire->ring<<" straw="<<wire->straw<<" stereo="<<wire->stereo<<endl;
1080 if(fabs(s) > wire->L/2.0)continue; // if wire doesn't cross circle, skip hit
1081
1082
1083 // Determine 3d space point for this hit
1084 DCDCTrkHit mytrkhit = *trkhit; // we need to make a copy since x_stereo,... are unique based on the cadidate
1085 DVector3 pos = wire->origin + s*wire->udir;
1086 mytrkhit.x_stereo = pos.X();
1087 mytrkhit.y_stereo = pos.Y();
1088 mytrkhit.z_stereo = pos.Z();
1089
1090 // Verify that this hit is reasonably close to the axial hits in X and Y
1091 // If not, then drop this hit for this seed.
1092 double phi_diff = fabs(pos.Phi() - seed.phi_avg);
1093 if(phi_diff>M_PI3.14159265358979323846)phi_diff = 2.0*M_PI3.14159265358979323846 - phi_diff;
1094 phi_diff*=57.3; // convert to degrees
1095 if(fabs(phi_diff)>MAX_SEED_LINK_ANGLE){ // yes, the fabs is needed ...
1096 if(DEBUG_LEVEL>4)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1096<<" "
<<"rejecting stereo hit at phi="<<pos.Phi()<<" for being too far away from axial hits(phi_diff="<<phi_diff<<")"<<endl;
1097 continue;
1098 }
1099 mytrkhit.phi_stereo = atan2(mytrkhit.y_stereo-R.Y(), mytrkhit.x_stereo-R.X());
1100 R*=-1.0; // make R point from center of circle to beamline instead of other way around
1101 if(DEBUG_LEVEL>15){
1102 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1102<<" "
<<" --- wire->udir X, Y, Z = "<<wire->udir.X()<<", "<<wire->udir.Y()<<", "<<wire->udir.Z()<<endl;
1103 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1103<<" "
<<" -- ring="<<wire->ring<<" trkhit->z_stereo="<<trkhit->z_stereo<<" trkhit->y_stereo="<<trkhit->y_stereo<<" trkhit->x_stereo="<<trkhit->x_stereo<<endl;
1104 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1104<<" "
<<" -- phi_stereo="<<trkhit->phi_stereo<<" R.Phi()="<<R.Phi()<<" (X,Y)=("<<R.X()<<", "<<R.Y()<<")"<<endl;
1105 _DBG__std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1105<<std::endl
;
1106 }
1107 mytrkhit.phi_stereo -= R.Phi(); // make angle relative to beamline
1108
1109 // We want this to go either from 0 to +2pi for positive charge, or
1110 // 0 to -2pi for negative.
1111 double phi_hi = seed.fit.q>0.0 ? +2.0*M_PI3.14159265358979323846:0.0;
1112 double phi_lo = seed.fit.q>0.0 ? 0.0:-2.0*M_PI3.14159265358979323846;
1113 while(mytrkhit.phi_stereo<phi_lo){
1114 mytrkhit.phi_stereo+=2.0*M_PI3.14159265358979323846;
1115 }
1116 while(mytrkhit.phi_stereo>phi_hi){
1117 mytrkhit.phi_stereo-=2.0*M_PI3.14159265358979323846;
1118 }
1119 mytrkhit.flags |= VALID_STEREO;
1120 seed.stereo_hits.push_back(mytrkhit);
1121 if(DEBUG_LEVEL>10)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1121<<" "
<<"Adding CDC stereo hit: ring="<<mytrkhit.hit->wire->ring<<" straw="<<mytrkhit.hit->wire->straw<<endl;
1122 }
1123 if(DEBUG_LEVEL>5)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1123<<" "
<<"Num stereo hits: "<<seed.stereo_hits.size()<<endl;
1124}
1125
1126//------------------
1127// FindThetaZ
1128//------------------
1129void DTrackCandidate_factory_CDC::FindThetaZ(DCDCSeed &seed)
1130{
1131 // Decide whether to use the histogramming method or the
1132 // straight track method base on the transverse momentum
1133if(DEBUG_LEVEL>2)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1133<<" "
<<"p_trans:"<<seed.fit.p_trans<<endl;
1134//if(seed.fit.p_trans<3.0)
1135 if (true)
1136 {
1137 FindTheta(seed, TARGET_Z_MIN, TARGET_Z_MAX);
1138 FindZ(seed, seed.theta_min, seed.theta_max);
1139 }else{
1140 FindThetaZStraightTrack(seed);
1141
1142 // The value of p_trans that was originally determined
1143 // by DQuickFit::FitCircleStraightTrack() can often lead
1144 // to a total momentum larger than the beam momentum.
1145 // Re-estimate p_trans limiting the search with the
1146 // theta we just found.
1147 seed.fit.SearchPtrans(9.0*sin(seed.theta), 0.1);
1148 //seed.fit.QuickPtrans();
1149 if(DEBUG_LEVEL>2)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1149<<" "
<<"p_trans from search:"<<seed.fit.p_trans<<" (ptot="<<seed.fit.p_trans/sin(seed.theta)<<")"<<endl;
1150 }
1151
1152 // If z_vertex is not inside the target limits, then flag this
1153 // seed as invalid.
1154 /*
1155 if(seed.z_vertex<TARGET_Z_MIN || seed.z_vertex>TARGET_Z_MAX){
1156 if(DEBUG_LEVEL>3)_DBG_<<"Seed z-vertex outside of target range (z="<<seed.z_vertex<<" TARGET_Z_MIN="<<TARGET_Z_MIN<<" TARGET_Z_MAX="<<TARGET_Z_MAX<<endl;
1157 seed.valid=false;
1158 }
1159
1160 */
1161 return;
1162}
1163
1164//------------------
1165// FindThetaZStraightTrack
1166//------------------
1167void DTrackCandidate_factory_CDC::FindThetaZStraightTrack(DCDCSeed &seed)
1168{
1169 /// In the case of high momentum tracks, the values of phi_stereo will
1170 /// all be close together (and near 0 or +-2pi). For these cases,
1171 /// we calculate theta from r and z points which should be pretty linear.
1172
1173 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1173<<" "
<<"Fitting theta and z for high transverse momentum track (p_trans="<<seed.fit.p_trans<<")"<<endl;
1174
1175 // Do a linear regression of R vs. Z for stereo hits. First, we make
1176 // a list of the hits we'll use.
1177 vector<double> r;
1178 vector<double> z;
1179 for(unsigned int i=0; i<seed.stereo_hits.size(); i++){
1180 DCDCTrkHit *trkhit = &seed.stereo_hits[i];
1181 if(!trkhit->flags&VALID_STEREO)continue;
1182
1183 //double R = sqrt(pow(trkhit->x_stereo,2.0) + pow(trkhit->y_stereo,2.0));
1184 double R=sqrt(trkhit->x_stereo*trkhit->x_stereo
1185 +trkhit->y_stereo*trkhit->y_stereo);
1186 r.push_back(R);
1187 z.push_back(trkhit->z_stereo);
1188 }
1189
1190 // Add center of target as a point to constrain the fit a little more
1191 r.push_back(0.0);
1192 z.push_back(TARGET_Z);
1193
1194 // Calculate average z and r
1195 double Ravg=0.0, Zavg=0.0;
1196 for(unsigned int i=0; i<r.size(); i++){
1197 Ravg += r[i];
1198 Zavg += z[i];
1199 }
1200 Ravg /= (double)r.size();
1201 Zavg /= (double)z.size();
1202
1203 // Now, do the regression
1204 double Szr=0.0, Szz=0.0, Srr=0.0;;
1205 for(unsigned int i=0; i<r.size(); i++){
1206 if(DEBUG_LEVEL>4)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1206<<" "
<<"r="<<r[i]<<"\t z="<<z[i]<<" Szz_i="<<pow((z[i] - Zavg), 2.0)<<" Srr_i="<<pow((r[i] - Ravg),2.0)<<endl;
1207 double dz=z[i] - Zavg;
1208 double dr=r[i] - Ravg;
1209 /*
1210 Szr += (z[i] - Zavg)*(r[i] - Ravg);
1211 Szz += pow((z[i] - Zavg), 2);
1212 Srr += pow((r[i] - Ravg), 2);
1213 */
1214 Szr += dz*dr;
1215 Szz += dz*dz;
1216 Srr += dr*dr;
1217 }
1218
1219 if(Szz>Srr){
1220 // track is more horizontal
1221 seed.z_vertex = Zavg - Ravg*Szz/Szr;
1222 seed.theta = atan2(Szr, Szz);
1223 }else{
1224 // track is more vertical
1225 seed.z_vertex = Zavg - Ravg*Szr/Srr;
1226 seed.theta = M_PI_21.57079632679489661923 - atan2(Szr, Srr);
1227 }
1228 if(seed.theta<0.0){
1229 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1229<<" "
<<"theta less than 0 ("<<seed.theta<<") this simply shoudn't happen!"<<endl;
1230 seed.theta+=M_PI3.14159265358979323846;
1231 }
1232 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1232<<" "
<<"theta="<<seed.theta<<" z_vertex="<<seed.z_vertex<<endl;
1233 if(DEBUG_LEVEL>4){
1234 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1234<<" "
<<"Szz="<<Szz<<" Srr="<<Srr<<endl;
1235 double z_vertex = Zavg - Ravg*Szz/Szr;
1236 double theta = atan2(Szr, Szz);
1237 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1237<<" "
<<"for Szz>Srr : theta="<<theta<<" z_vertex="<<z_vertex<<endl;
1238 z_vertex = Zavg - Ravg*Szr/Srr;
1239 theta = M_PI_21.57079632679489661923 - atan2(Szr, Srr);
1240 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1240<<" "
<<"for Szz<=Srr : theta="<<theta<<" z_vertex="<<z_vertex<<endl;
1241 }
1242}
1243
1244//------------------
1245// FindTheta
1246//------------------
1247void DTrackCandidate_factory_CDC::FindTheta(DCDCSeed &seed, double target_z_min, double target_z_max)
1248{
1249 /// Find the theta value using the valid stereo hits from <i>seed</i>. The values
1250 /// for phi_stereo and z_stereo are assumed to be valid as is the status of the
1251 /// VALID_STEREO bit in flags. The value of seed.fit.r0 is also used to calculate
1252 /// theta.
1253 ///
1254 /// This uses a histogramming technique that looks at the overlaps of the
1255 /// angle ranges subtended by each hit between the given target limits.
1256 /// The overlaps usually lead to a range of values for theta. The limits
1257 /// of these are stored in the theta_min and theta_max fields of the seed.
1258 /// The centroid of the range is stored in the theta field.
1259
1260 // We use a simple array to store our histogram here. We don't want to use
1261 // ROOT histograms because they are not thread safe.
1262 unsigned int Nbins = 1000;
1263 unsigned int hist[Nbins];
1264 for(unsigned int i=0; i<Nbins; i++)hist[i] = 0; // clear histogram
1265 double bin_width = 2.0*M_PI3.14159265358979323846/(double)Nbins;
1266 double hist_low_limit = -M_PI3.14159265358979323846; // lower edge of histogram limits
1267
1268 // Loop over CDC hits, filling the histogram
1269 double r0 = seed.fit.r0;
1270 for(unsigned int i=0; i<seed.stereo_hits.size(); i++){
1271 DCDCTrkHit *trkhit = &seed.stereo_hits[i];
1272 if(!trkhit->flags&VALID_STEREO)continue;
1273
1274 // Calculate upper and lower limits in theta
1275 double alpha = r0*trkhit->phi_stereo;
1276 if(seed.fit.q<0.0)alpha = -alpha;
1277 double tmin = atan2(alpha, trkhit->z_stereo - target_z_min);
1278 double tmax = atan2(alpha, trkhit->z_stereo - target_z_max);
1279 if(tmin>tmax){
1280 double tmp = tmin;
1281 tmin=tmax;
1282 tmax=tmp;
1283 }
1284 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1284<<" "
<<" -- phi_stereo="<<trkhit->phi_stereo<<" z_stereo="<<trkhit->z_stereo<<" alpha="<<alpha<<endl;
1285 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1285<<" "
<<" -- tmin="<<tmin<<" tmax="<<tmax<<endl;
1286
1287 // Find index of bins corresponding to tmin and tmax
1288 unsigned int imin = (unsigned int)floor((tmin-hist_low_limit)/bin_width);
1289 unsigned int imax = (unsigned int)floor((tmax-hist_low_limit)/bin_width);
1290
1291 // If entire range of this hit is outside of the histogram limit
1292 // then discard this hit.
1293 if(imax<0 || imin>=Nbins)continue;
1294
1295 // Clip limits of bin range to our histogram limits
1296 if(imin<0)imin=0;
1297 if(imin>=Nbins)imin=Nbins-1;
1298 if(imax<0)imax=0;
1299 if(imax>=Nbins)imax=Nbins-1;
1300
1301 // Increment all bins between imin and imax
1302 for(unsigned int j=imin; j<=imax; j++)hist[j]++;
1303 }
1304
1305 // Look for the indexes of the plateau
1306 unsigned int istart=0;
1307 unsigned int iend=0;
1308 for(unsigned int i=1; i<Nbins; i++){
1309 if(hist[i]>hist[istart]){
1310 istart = i;
1311 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1311<<" "
<<" -- istart="<<istart<<" (theta="<<hist_low_limit + bin_width*(0.5+(double)istart)<<" , N="<<hist[i]<<")"<<endl;
1312 }
1313 if(hist[i] == hist[istart])iend = i;
1314 }
1315
1316 // If there are no entries in the histogram, then flag this seed as invalid
1317 if(hist[istart]==0.0)seed.valid=false;
1318
1319 // Calculate theta limits
1320 seed.theta_min = hist_low_limit + bin_width*(0.5+(double)istart);
1321 seed.theta_max = hist_low_limit + bin_width*(0.5+(double)iend);
1322 seed.theta = (seed.theta_max + seed.theta_min)/2.0;
1323 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1323<<" "
<<"istart="<<istart<<" iend="<<iend<<" theta_min="<<seed.theta_min<<" theta_max="<<seed.theta_max<<endl;
1324}
1325
1326//------------------
1327// FindZ
1328//------------------
1329void DTrackCandidate_factory_CDC::FindZ(DCDCSeed &seed, double theta_min, double theta_max)
1330{
1331 /// Find the z value of the vertex using the valid stereo hits from <i>seed</i>. The values
1332 /// for phi_stereo and z_stereo are assumed to be valid as is the status of the
1333 /// VALID_STEREO bit in flags.
1334 ///
1335 /// This uses a histogramming technique that looks at the overlaps of the
1336 /// z ranges subtended by each hit between the given theta limits.
1337 /// The overlaps usually lead to a range of values for z_vertex. The limits
1338 /// of these are stored in the z_min and z_max fields of the seed.
1339 /// The centroid of the range is stored in the z_vertex field.
1340
1341 // We use a simple array to store our histogram here. We don't want to use
1342 // ROOT histograms because they are not thread safe.
1343 unsigned int Nbins = 300;
1344 unsigned int hist[Nbins];
1345 for(unsigned int i=0; i<Nbins; i++)hist[i] = 0; // clear histogram
1346 double bin_width = 0.5; // bins are 5mm
1347 double hist_low_limit = 0.0; // lower edge of histogram limits
1348
1349 // Loop over CDC hits, filling the histogram
1350 double r0 = seed.fit.r0;
1351 double tan_alpha_min = tan(theta_min)/r0;
1352 double tan_alpha_max = tan(theta_max)/r0;
1353 for(unsigned int i=0; i<seed.stereo_hits.size(); i++){
1354 DCDCTrkHit *trkhit = &seed.stereo_hits[i];
1355 if(!trkhit->flags&VALID_STEREO)continue;
1356
1357 // Calculate upper and lower limits in z
1358 double q_sign = seed.fit.q>0.0 ? +1.0:-1.0;
1359 double zmin = trkhit->z_stereo - q_sign*trkhit->phi_stereo/tan_alpha_min;
1360 double zmax = trkhit->z_stereo - q_sign*trkhit->phi_stereo/tan_alpha_max;
1361 if(zmin>zmax){
1362 double tmp = zmin;
1363 zmin=zmax;
1364 zmax=tmp;
1365 }
1366 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1366<<" "
<<" -- phi_stereo="<<trkhit->phi_stereo<<" z_stereo="<<trkhit->z_stereo<<endl;
1367 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1367<<" "
<<" -- zmin="<<zmin<<" zmax="<<zmax<<endl;
1368
1369 // Find index of bins corresponding to tmin and tmax
1370 unsigned int imin = (unsigned int)floor((zmin-hist_low_limit)/bin_width);
1371 unsigned int imax = (unsigned int)floor((zmax-hist_low_limit)/bin_width);
1372
1373 // If entire range of this hit is outside of the histogram limit
1374 // then discard this hit.
1375 if(imax<=0 || imin>=Nbins)continue;
1376
1377 // Clip limits of bin range to our histogram limits
1378 if(imin<0)imin=0;
1379 if(imin>=Nbins)imin=Nbins-1;
1380 if(imax<0)imax=0;
1381 if(imax>=Nbins)imax=Nbins-1;
1382
1383 // Increment all bins between imin and imax
1384 for(unsigned int j=imin; j<=imax; j++)hist[j]++;
1385 }
1386
1387 // Look for the indexes of the plateau
1388 unsigned int istart=0;
1389 unsigned int iend=0;
1390 for(unsigned int i=1; i<Nbins; i++){
1391 if(hist[i]>hist[istart]){
1392 istart = i;
1393 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1393<<" "
<<" -- istart="<<istart<<" (z="<<hist_low_limit + bin_width*(0.5+(double)istart)<<" , N="<<hist[i]<<")"<<endl;
1394 }
1395 if(hist[i] == hist[istart])iend = i;
1396 }
1397
1398 // If there are no entries in the histogram, then flag this seed as invalid
1399 if(hist[istart]==0.0)seed.valid=false;
1400
1401 // Calculate z limits
1402 seed.z_min = hist_low_limit + bin_width*(0.5+(double)istart);
1403 seed.z_max = hist_low_limit + bin_width*(0.5+(double)iend);
1404 seed.z_vertex = (seed.z_max + seed.z_min)/2.0;
1405 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1405<<" "
<<"istart="<<istart<<" iend="<<iend<<" z_min="<<seed.z_min<<" z_max="<<seed.z_max<<" hits[istart]="<<hist[istart]<<endl;
1406}
1407
1408//------------------
1409// NumEligibleSeedHits
1410//------------------
1411int DTrackCandidate_factory_CDC::NumEligibleSeedHits(vector<DCDCTrkHit*> &hits)
1412{
1413 int N=0;
1414 for(unsigned int i=0; i<hits.size(); i++){
1415 if((hits[i]->flags & (USED | CANT_BE_IN_SEED | OUT_OF_TIME)) == 0)N++;
1416 }
1417
1418 return N;
1419}
1420
1421//------------------
1422// DCDCSeed::DCDCSeed
1423//------------------
1424DTrackCandidate_factory_CDC::DCDCSeed::DCDCSeed()
1425{
1426 phi_avg = 0.0;
1427 tdrift_avg = 0.0;
1428 linked = false;
1429 valid = false;
1430 theta = 0.0;
1431 z_vertex = 0.0;
1432 q = 0.0;
1433 theta_min = 0.0;
1434 theta_max = 0.0;
1435 z_min = 0.0;
1436 z_max = 0.0;
1437}
1438
1439//------------------
1440// DCDCSeed::Merge
1441//------------------
1442void DTrackCandidate_factory_CDC::DCDCSeed::Merge(DCDCSeed& seed)
1443{
1444 // Need avg. phi based on hits from both seeds
1445 double x = (double)hits.size()*cos(phi_avg);
1446 double y = (double)hits.size()*sin(phi_avg);
1447
1448 for(unsigned int i=0; i<seed.hits.size(); i++){
1449 hits.push_back(seed.hits[i]);
1450
1451 x += cos(seed.hits[i]->hit->wire->phi);
1452 y += sin(seed.hits[i]->hit->wire->phi);
1453 }
1454
1455 phi_avg = atan2(y,x);
1456 if(phi_avg<0.0)phi_avg += 2.0*M_PI3.14159265358979323846;
1457}
1458
1459//------------------
1460// DCDCSeed::MinDist2
1461//------------------
1462double DTrackCandidate_factory_CDC::DCDCSeed::MinDist2(DCDCSeed& seed)
1463{
1464 /// Returns the minimum distance squared between this and the given seed.
1465 /// Only the first and last hits of each seed's hit list are used
1466 /// to calculate a maximum of 4 distances (minimum of 1) of which, the
1467 /// smallest is returned.
1468 if(hits.size()==0 || seed.hits.size()==0){
1469 _DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1469<<" "
<<"Number of seed hits 0! (Nthis="<<hits.size()<<" ,Nseed="<<seed.hits.size()<<")"<<endl;
1470 return 1.0E10;
1471 }
1472
1473 // This is kind of messy looking, but it avoids extra calls to
1474 // DCDCTrkHit::Dist2 that aren't necessary.
1475 double d2min = hits[0]->Dist2(seed.hits[0]);
1476 if(hits.size()>0){
1477 double d2 = hits[hits.size()-1]->Dist2(seed.hits[0]);
1478 if(d2<d2min)d2min = d2;
1479
1480 if(seed.hits.size()>0){
1481 double d2 = hits[hits.size()-1]->Dist2(seed.hits[seed.hits.size()-1]);
1482 if(d2<d2min)d2min = d2;
1483 }
1484 }
1485 if(seed.hits.size()>0){
1486 double d2 = hits[0]->Dist2(seed.hits[seed.hits.size()-1]);
1487 if(d2<d2min)d2min = d2;
1488 }
1489
1490 return d2min;
1491}
1492
1493//------------------
1494// DCDCSeed::FindAverageBz
1495//------------------
1496double DTrackCandidate_factory_CDC::DCDCSeed::FindAverageBz( const DMagneticFieldMap *bfield
1497)
1498{
1499 //return 2.0;
1500 if(!bfield)return 0.0;
1501
1502 double Bz_sum=0.0;
1503 for(unsigned int i=0; i<stereo_hits.size(); i++){
1504 DCDCTrkHit *hit = &stereo_hits[i];
1505 Bz_sum += bfield->GetBz(hit->x_stereo,hit->y_stereo,
1506 hit->z_stereo);
1507 }
1508
1509 return Bz_sum/(double)(stereo_hits.size());
1510}
1511
1512
1513//------------------
1514// FindThetaZRegression
1515//------------------
1516// Linear regression to find tan(lambda) and z_vertex
1517jerror_t DTrackCandidate_factory_CDC::FindThetaZRegression(DCDCSeed &seed){
1518
1519 if(DEBUG_LEVEL>3)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1519<<" "
<<"Finding theta and z via linear regression method."<<endl;
1520
1521 if (seed.fit.normal.Mag()==0.) return VALUE_OUT_OF_RANGE;
1522 // Vector of intersections between the circles of the measurements and the plane intersecting the Riemann surface
1523 vector<DVector3_with_perp>intersections;
1524 DVector3_with_perp beam(0,0,TARGET_Z);
1525 intersections.push_back(beam);
1526
1527 // CDC stereo hits
1528 for (unsigned int m=0;m<seed.stereo_hits.size();m++){
1529 unsigned int numbits=8*sizeof(unsigned int);
1530 seed.HitBitPattern[seed.stereo_hits[m].index/numbits]
1531 |=1<<seed.stereo_hits[m].index%numbits;
1532
1533 DCDCTrkHit *trkhit=&seed.stereo_hits[m];
1534 double R2=trkhit->x_stereo*trkhit->x_stereo+trkhit->y_stereo*trkhit->y_stereo;
1535
1536 DVector3_with_perp intersection;
1537 DVector3 N=seed.fit.normal;
1538 //double c0=seed.fit.c_origin;
1539 double A=seed.fit.c_origin+R2*N.Z();
1540 double B=N.Perp();
1541 double C=B*R2-A*A;
1542
1543 if (C>=0) {
1544 double sqrtC=sqrt(C);
1545 double x1=(-N.X()*A+N.Y()*sqrtC)/B;
1546 double y1=(-N.Y()*A-N.X()*sqrtC)/B;
1547 double x2=(-N.X()*A-N.Y()*sqrtC)/B;
1548 double y2=(-N.Y()*A+N.X()*sqrtC)/B;
1549
1550 if (fabs(trkhit->y_stereo-y1)<fabs(trkhit->y_stereo-y2)){
1551 intersection.SetX(x1);
1552 intersection.SetY(y1);
1553 }
1554 else{
1555 intersection.SetX(x2);
1556 intersection.SetY(y2);
1557 }
1558 intersection.SetZ(trkhit->z_stereo);
1559
1560 intersections.push_back(intersection);
1561 if(DEBUG_LEVEL>5)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1561<<" "
<<"Adding CDC hit "<<m<<" z="<<intersection.z()<<endl;
1562
1563 }
1564
1565 }
1566
1567 // The SortIntersections method requires the perp field to be valid
1568 // for all objects. Go through and fill in those fields now.
1569 for(unsigned int i=0; i<intersections.size(); i++)intersections[i].CalcPerp();
1570
1571 // Now, sort the entries
1572 sort(intersections.begin(),intersections.end(),SortIntersections);
1573
1574 // Compute the arc lengths between (0,0) and (xi,yi)
1575 vector<double>arclengths(intersections.size());
1576 vector<double>var_z(intersections.size());
1577 arclengths[0]=0.;
1578 //double temp=1.6/sin(6.*M_PI/180.);
1579 //double varz=temp*temp/12.;
1580 double two_rc=2.*seed.fit.r0;
1581 for (unsigned int m=1;m<arclengths.size();m++){
1582 double diffx=intersections[m].x()-intersections[0].x();
1583 double diffy=intersections[m].y()-intersections[0].y();
1584 double chord=sqrt(diffx*diffx+diffy*diffy);
1585 double ratio=chord/two_rc;
1586 double s=(ratio<1.)?two_rc*asin(ratio):M_PI_21.57079632679489661923*two_rc;
1587
1588 arclengths[m]=s;
1589 //var_z[m]=varz;
1590 var_z[m]=19.52;
1591 }
1592
1593 //Linear regression to find z0, tanl
1594 double tanl=0.,z0=0.;
1595 if (arclengths.size()>2){ // Do fit only if have more than one measurement
1596 //var_z[0]=30.*30./12.; // Use length of the target
1597 var_z[0]=75.;
1598 double sumv=0.,sumx=0.;
1599 double sumy=0.,sumxx=0.,sumxy=0.;
1600 for (unsigned int m=0;m<intersections.size();m++){
1601 double temp=1./var_z[m];
1602 sumv+=temp;
1603 sumx+=arclengths[m]*temp;
1604 sumy+=intersections[m].z()*temp;;
1605 sumxx+=arclengths[m]*arclengths[m]*temp;
1606 sumxy+=arclengths[m]*intersections[m].z()*temp;
1607 }
1608 double Delta=sumv*sumxx-sumx*sumx;
1609 if (Delta==0.) return VALUE_OUT_OF_RANGE;
1610
1611 tanl=(sumv*sumxy-sumx*sumy)/Delta;
1612 z0=(sumxx*sumy-sumx*sumxy)/Delta;
1613 }
1614 else if(arclengths.size()==2){
1615 z0=TARGET_Z;
1616 tanl=(intersections[1].z()-z0)/arclengths[1];
1617 }else{
1618 if(DEBUG_LEVEL>5)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1618<<" "
<<"Fit failed for theta-z via regressionz due to too few hits with z-info"<<endl;
1619 return VALUE_OUT_OF_RANGE;
1620 }
1621
1622 if (z0>TARGET_Z_MAX || z0<TARGET_Z_MIN){
1623 if(DEBUG_LEVEL>5)_DBG_std::cerr<<"DTrackCandidate_factory_CDC.cc"<<":"<<
1623<<" "
<<"Fit failed for theta-z via regressionz value out of target range (z="<<z0<<")"<<endl;
1624 return VALUE_OUT_OF_RANGE;
1625 }
1626
1627 seed.theta=M_PI_21.57079632679489661923-atan(tanl);
1628 seed.z_vertex=z0;
1629
1630 return NOERROR;
1631}
1632
1633// Get the position and momentum at a fixed radius from the beam line
1634jerror_t DTrackCandidate_factory_CDC::GetPositionAndMomentum(DCDCSeed &seed,
1635 DVector3 &pos,
1636 DVector3 &mom){
1637 // Direction tangent and transverse momentum
1638 double tanl=tan(M_PI_21.57079632679489661923-seed.theta);
1639 double pt=seed.fit.p_trans*fabs(seed.FindAverageBz(bfield))/2.0;
1640
1641 // Squared radius of cylinder outside start counter but inside CDC inner
1642 // radius
1643 double r2=90.0;
1644
1645 // Circle parameters
1646 double xc=seed.fit.x0;
1647 double yc=seed.fit.y0;
1648 double rc=seed.fit.r0;
1649 double rc2=rc*rc;
1650 double xc2=xc*xc;
1651 double yc2=yc*yc;
1652 double xc2_plus_yc2=xc2+yc2;
1653
1654 // variables needed for intersection of circles
1655 double a=(r2-xc2_plus_yc2-rc2)/(2.*rc);
1656 double temp1=yc*sqrt(xc2_plus_yc2-a*a);
1657 double temp2=xc*a;
1658 double cosphi_plus=(temp2+temp1)/xc2_plus_yc2;
1659 double cosphi_minus=(temp2-temp1)/xc2_plus_yc2;
1660
1661 // Check for intersections
1662 if(!isfinite(temp1) || !isfinite(temp2)){
1663 // We did not find an intersection between the two circles, so return
1664 // sensible defaults for pos and
1665 double my_phi=seed.fit.phi;
1666 double sinphi=sin(my_phi);
1667 double cosphi=cos(my_phi);
1668 double D=-seed.fit.q*rc-xc/sinphi;
1669 pos.SetXYZ(-D*sinphi,D*cosphi,seed.z_vertex);
1670 mom.SetXYZ(pt*cosphi,pt*sinphi,pt*tanl);
1671
1672 return NOERROR;
1673 }
1674
1675 // if we have intersections, find both solutions
1676 double phi_plus=-acos(cosphi_plus);
1677 double phi_minus=-acos(cosphi_minus);
1678 double x_plus=xc+rc*cosphi_plus;
1679 double x_minus=xc+rc*cosphi_minus;
1680 double y_plus=yc+rc*sin(phi_plus);
1681 double y_minus=yc+rc*sin(phi_minus);
1682
1683 // if the resulting radial position on the circle from the fit does not agree
1684 // with the radius to which we are matching, we have the wrong sign for phi+
1685 // or phi-
1686 double r2_plus=x_plus*x_plus+y_plus*y_plus;
1687 double r2_minus=x_minus*x_minus+y_minus*y_minus;
1688 if (fabs(r2-r2_plus)>EPS1e-3){
1689 phi_plus*=-1.;
1690 y_plus=yc+rc*sin(phi_plus);
1691 }
1692 if (fabs(r2-r2_minus)>EPS1e-3){
1693 phi_minus*=-1.;
1694 y_minus=yc+rc*sin(phi_minus);
1695 }
1696
1697 // Choose phi- or phi+ depending on proximity to one of the cdc hits
1698 double xwire=seed.hits[0]->hit->wire->origin.x();
1699 double ywire=seed.hits[0]->hit->wire->origin.y();
1700 double dx=x_minus-xwire;
1701 double dy=y_minus-ywire;
1702 double d2_minus=dx*dx+dy*dy;
1703 dx=x_plus-xwire;
1704 dy=y_plus-ywire;
1705 double d2_plus=dx*dx+dy*dy;
1706 if (d2_plus>d2_minus){
1707 phi_minus*=-1.;
1708 if (seed.fit.q<0) phi_minus+=M_PI3.14159265358979323846;
1709 double dphi=M_PI_21.57079632679489661923-phi_minus-seed.fit.phi;
1710 while (dphi>2.*M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
1711 while (dphi<-2.*M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
1712 if (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
1713 if (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
1714 pos.SetXYZ(x_minus,y_minus,seed.z_vertex+seed.fit.q*rc*dphi*tanl);
1715 mom.SetXYZ(pt*sin(phi_minus),pt*cos(phi_minus),pt*tanl);
1716
1717 }
1718 else{
1719 phi_plus*=-1.;
1720 if (seed.fit.q<0) phi_plus+=M_PI3.14159265358979323846;
1721 double dphi=M_PI_21.57079632679489661923-phi_plus-seed.fit.phi;
1722 while (dphi>2.*M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
1723 while (dphi<-2.*M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
1724 if (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
1725 if (dphi>M_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
1726 pos.SetXYZ(x_plus,y_plus,seed.z_vertex+seed.fit.q*rc*dphi*tanl);
1727 mom.SetXYZ(pt*sin(phi_plus),pt*cos(phi_plus),pt*tanl);
1728
1729 }
1730
1731 return NOERROR;
1732}