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.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.cc

libraries/TRACKING/DTrackCandidate_factory.cc

1// $Id$
2//
3// File: DTrackCandidate_factory.cc
4// Created: Mon Jul 18 15:23:04 EDT 2005
5// Creator: davidl (on Darwin wire129.jlab.org 7.8.0 powerpc)
6//
7
8/// Factory to match track candidates generated by the FDC- and CDC-specific
9/// track finding codes. The code uses several algorithms in the following
10/// order of precedence:
11/// Method 1: Swims cdc candidates pointing in the forward direction
12/// and tries to match them geometrically to fdc candidates.
13/// Method 2: Projects the fdc candidates into the cdc region and tries
14/// to match to the cdc hits in each cdc candidate that points
15/// in the forward direction.
16/// Method 3: Similar to method 2, except that it projects a cdc
17/// candidate into the FDC region.
18/// Method 4: Matches left-over fdc candidates to other left-over fdc
19/// candidates.
20/// Method 5: Matches cdc candidates that do not point toward the cdc
21/// endplate that were not matched by previous methods to fdc
22/// candidates.
23/// Method 6: Tries to match stray unused cdc hits with fdc candidates
24/// Method 7: Alternate method to match leftover fdc candidates that
25/// have already been matched to other track candidates
26/// Method 8: Attempts to "improve" a cdc candidate to be matched to an
27/// FDC candidate with an assumption of the hit position in
28/// outermost stereo straw
29/// Methods 9-13: Various tricks to try to associate segments in the FDC
30/// with other segments or tracks
31/// If a match is found, the code attempts to improve the track parameters by
32/// redoing the Riemann Circle fit with the additional hits. If an fdc
33/// candidate is matched to a cdc candidate, or several previously unused hits
34/// are added to the track, the code attempts to place the "start" position
35/// parameters of the track at a radius just outside the start counter.
36
37#include <cmath>
38using namespace std;
39
40#include "DTrackCandidate_factory.h"
41#include "DTrackCandidate_factory_CDC.h"
42#include "START_COUNTER/DSCHit.h"
43#include "DANA/DApplication.h"
44#include <JANA/JCalibration.h>
45#include <TRACKING/DHoughFind.h>
46
47#include <TROOT.h>
48#include <TH2F.h>
49#include <TMath.h>
50
51#define CUT10. 10.
52#define RADIUS_CUT50.0 50.0
53#define BEAM_VAR1. 1. // cm^2
54#define EPS0.001 0.001
55
56//------------------
57// cdc_fdc_match
58//------------------
59inline bool cdc_fdc_match(double p_fdc,double p_cdc,double dist){
60 //double frac=fabs(1.-p_cdc/p_fdc);
61 //double frac2=fabs(1.-p_fdc/p_cdc);
62 double p=p_fdc;
63 if (p_cdc <p ) p=p_cdc;
64 if (dist<10. && dist <4.+1.75/p
65 //&& (frac<0.5 || frac2<0.5)
66 ) return true;
67 return false;
68}
69
70//------------------
71// SegmentSortByLayerincreasing
72//------------------
73inline bool SegmentSortByLayerincreasing(const DFDCSegment* const &segment1, const DFDCSegment* const &segment2) {
74 // Compare DFDCSegment->DFDCPseudo[0]->DFDCWire->layer
75 int layer1 = 100; // defaults just in case there is a segment with no hits
76 int layer2 = 100;
77
78 if(segment1->hits.size()>0)layer1=segment1->hits[0]->wire->layer;
79 if(segment2->hits.size()>0)layer2=segment2->hits[0]->wire->layer;
80
81 return layer1 < layer2;
82}
83
84//------------------
85// CDCHitSortByLayerincreasing
86//------------------
87inline bool CDCHitSortByLayerincreasing(const DCDCTrackHit* const &hit1, const DCDCTrackHit* const &hit2) {
88 // Used to sort CDC hits by layer (ring) with innermost layer hits first
89
90 // if same ring, sort by wire number
91 if(hit1->wire->ring == hit2->wire->ring)
92 {
93 if(hit1->wire->straw == hit2->wire->straw)
94 return (hit1->dE > hit2->dE);
95 return hit1->wire->straw < hit2->wire->straw;
96 }
97
98 return hit1->wire->ring < hit2->wire->ring;
99}
100
101//------------------
102// FDCHitSortByLayerincreasing
103//------------------
104inline bool FDCHitSortByLayerincreasing(const DFDCPseudo* const &hit1, const DFDCPseudo* const &hit2) {
105 // Used to sort FDC hits by layer with most upstream layer hits first
106 // if same layer, sort by wire number
107 if(hit1->wire->layer == hit2->wire->layer)
108 {
109 if(hit1->wire->wire == hit2->wire->wire)
110 return (hit1->dE > hit2->dE);
111 return (hit1->wire->wire < hit2->wire->wire);
112 }
113
114 return hit1->wire->layer < hit2->wire->layer;
115}
116
117//------------------
118// init
119//------------------
120jerror_t DTrackCandidate_factory::init(void)
121{
122 MAX_NUM_TRACK_CANDIDATES = 20;
123
124 return NOERROR;
125}
126
127//------------------
128// brun
129//------------------
130jerror_t DTrackCandidate_factory::brun(JEventLoop* eventLoop,int32_t runnumber){
131 DApplication* dapp=dynamic_cast<DApplication*>(eventLoop->GetJApplication());
132 const DGeometry *dgeom = dapp->GetDGeometry(runnumber);
133 bfield = dapp->GetBfield(runnumber);
134 FactorForSenseOfRotation=(bfield->GetBz(0.,0.,65.)>0.)?-1.:1.;
1
Assuming the condition is false
2
'?' condition is false
135
136 // Get start counter geometry;
137 dgeom->GetStartCounterGeom(sc_pos,sc_norm);
138
139 dIsNoFieldFlag = (dynamic_cast<const DMagneticFieldMapNoField*>(bfield) != NULL__null);
3
Assuming field 'bfield' is equal to NULL
140 if(dIsNoFieldFlag
3.1
Field 'dIsNoFieldFlag' is false
3.1
Field 'dIsNoFieldFlag' is false
3.1
Field 'dIsNoFieldFlag' is false
)
4
Taking false branch
141 {
142 //Setting this flag makes it so that JANA does not delete the objects in _data. This factory will manage this memory.
143 //This is all of these pointers are just copied from the "StraightLine" factory, and should not be re-deleted.
144 SetFactoryFlag(NOT_OBJECT_OWNER);
145 }
146 else
147 ClearFactoryFlag(NOT_OBJECT_OWNER); //This factory will create it's own objects.
148
149 // Get the position of the exit of the CDC endplate from DGeometry
150 double endplate_z,endplate_dz,endplate_rmin;
151 dgeom->GetCDCEndplate(endplate_z,endplate_dz,endplate_rmin,endplate_rmax);
152 cdc_endplate.SetZ(endplate_z+endplate_dz);
153
154 dParticleID = NULL__null;
155 eventLoop->GetSingle(dParticleID);
5
Calling 'JEventLoop::GetSingle'
156
157 JCalibration *jcalib = dapp->GetJCalibration(runnumber);
158 map<string, double> targetparms;
159 if (jcalib->Get("TARGET/target_parms",targetparms)==false){
160 TARGET_Z = targetparms["TARGET_Z_POSITION"];
161 }
162 else{
163 dgeom->GetTargetZ(TARGET_Z);
164 }
165
166 // Initialize the stepper
167 stepper=new DMagneticFieldStepper(bfield);
168 stepper->SetStepSize(1.0);
169
170 DEBUG_HISTS=false;
171 gPARMS->SetDefaultParameter("TRKFIND:DEBUG_HISTS",DEBUG_HISTS);
172
173 if(DEBUG_HISTS){
174 dapp->Lock();
175 /*
176 match_center_dist2=(TH2F*)gROOT->FindObject("match_center_dist2");
177 if (!match_center_dist2){
178 match_center_dist2=new TH2F("match_center_dist2","larger radius vs matching distance squared between two circle centers",100,0,100.,100,0,100);
179 match_center_dist2->SetYTitle("r_{c} [cm]");
180 match_center_dist2->SetXTitle("(#Deltad)^{2} [cm^{2}]");
181 }
182 */
183 match_dist=(TH2F*)gROOT(ROOT::GetROOT())->FindObject("match_dist");
184 if (!match_dist){
185 match_dist=new TH2F("match_dist","Matching distance",
186 120,0.,60.,500,0,25.);
187 match_dist->SetXTitle("r (cm)");
188 match_dist->SetYTitle("#Deltar (cm)");
189 }
190 match_dist_vs_p=(TH2F*)gROOT(ROOT::GetROOT())->FindObject("match_dist_vs_p");
191 if (!match_dist_vs_p) {
192 match_dist_vs_p=new TH2F("match_dist_vs_p","Matching distance vs p",
193 50,0.,7.,100,0,25.);
194 match_dist_vs_p->SetYTitle("#Deltar (cm)");
195 match_dist_vs_p->SetXTitle("p (GeV/c)");
196 }
197 dapp->Unlock();
198 }
199
200 gPARMS->SetDefaultParameter("TRKFIND:MAX_NUM_TRACK_CANDIDATES", MAX_NUM_TRACK_CANDIDATES);
201
202 // MIN_NUM_HITS=6;
203 //gPARMS->SetDefaultParameter("TRKFIND:MIN_NUM_HITS", MIN_NUM_HITS);
204
205 DEBUG_LEVEL=0;
206 gPARMS->SetDefaultParameter("TRKFIND:DEBUG_LEVEL", DEBUG_LEVEL);
207
208 return NOERROR;
209}
210
211//------------------
212// erun
213//------------------
214jerror_t DTrackCandidate_factory::erun(void)
215{
216 if (stepper) {
217 delete stepper;
218 stepper = nullptr;
219 }
220
221 return NOERROR;
222}
223
224//------------------
225// erun
226//------------------
227jerror_t DTrackCandidate_factory::fini(void)
228{
229 if (stepper) {
230 delete stepper;
231 stepper = nullptr;
232 }
233
234 return NOERROR;
235}
236
237
238
239//------------------
240// evnt
241//------------------
242jerror_t DTrackCandidate_factory::evnt(JEventLoop *loop, uint64_t eventnumber)
243{
244 if(dIsNoFieldFlag)
245 {
246 //Clear previous objects: //JANA doesn't do it because NOT_OBJECT_OWNER was set
247 //It DID delete them though, in the "StraightLine" factory
248 _data.clear();
249
250 vector<const DTrackCandidate*> locStraightLineCandidates;
251 loop->Get(locStraightLineCandidates, "StraightLine");
252 for(size_t loc_i = 0; loc_i < locStraightLineCandidates.size(); ++loc_i)
253 _data.push_back(const_cast<DTrackCandidate*>(locStraightLineCandidates[loc_i]));
254 return NOERROR;
255 }
256
257 // Start counter hits
258 vector<const DSCHit *>schits;
259 loop->Get(schits);
260
261
262 // Clear private vectors
263 cdctrackcandidates.clear();
264 fdctrackcandidates.clear();
265 trackcandidates.clear();
266 mycdchits.clear();
267
268 // Get the track candidates from the CDC and FDC candidate finders
269 loop->Get(cdctrackcandidates, "CDC");
270 loop->Get(fdctrackcandidates, "FDCCathodes");
271
272 // List of cdc hits
273 loop->Get(mycdchits);
274
275 // Vectors for keeping track of cdc matches and projections to the endplate
276 vector<unsigned int> cdc_forward_ids;
277 vector<unsigned int> cdc_backward_ids;
278 vector<DVector3> cdc_endplate_projections;
279
280 // Vector to keep track of cdc hits used in candidates
281 vector<unsigned int>used_cdc_hits(mycdchits.size());
282
283 // vector to keep track of the matching status of each fdc candidate
284 vector<int>forward_matches(fdctrackcandidates.size());
285
286 // Normal vector for CDC endplate
287 DVector3 norm(0,0,1);
288
289 // Keep track of CDC hits that have already been used in track candidates
290 for(unsigned int i=0; i<cdctrackcandidates.size(); i++){
291 const DTrackCandidate *srccan = cdctrackcandidates[i];
292 for (unsigned int n=0;n<srccan->used_cdc_indexes.size();n++){
293 used_cdc_hits[srccan->used_cdc_indexes[n]]=1;
294 }
295 }
296 unsigned int num_unmatched_cdcs=0;
297 for (unsigned int i=0;i<used_cdc_hits.size();i++){
298 if (used_cdc_hits[i]==0) num_unmatched_cdcs++;
299 }
300
301 //Loop through the list of CDC candidates, flagging those that point toward
302 // the FDC.
303 for(unsigned int i=0; i<cdctrackcandidates.size(); i++){
304 const DTrackCandidate *srccan = cdctrackcandidates[i];
305 DVector3 mom=srccan->momentum();
306 DVector3 pos=srccan->position();
307
308 // Propagate track to CDC endplate
309 bool isForward=false;
310 if (fdctrackcandidates.size()>0){
311 if (mom.Theta()<M_PI_21.57079632679489661923){
312 // First do a quick projection using a helical model to see if it is
313 // worth adding this cdc candidate to the list of forward-going tracks
314 // that could pass into the FDC...
315 ProjectHelixToZ(cdc_endplate.z(),srccan->charge(),mom,pos);
316
317 if (pos.Perp()<60.){
318 // do an actual swim to the cdc endplate
319 mom=srccan->momentum();
320 pos=srccan->position();
321 stepper->SetCharge(srccan->charge());
322 stepper->SwimToPlane(pos,mom,cdc_endplate,norm,NULL__null);
323 if (pos.Perp()<60.){
324 cdc_endplate_projections.push_back(pos);
325 cdc_forward_ids.push_back(i);
326 isForward=true;
327 }
328 }
329 }
330 }
331 if (isForward==false){
332 cdc_backward_ids.push_back(i);
333 }
334 }
335
336 // Variables for candidate number accounting
337 int num_forward_cdc_cands_remaining=cdc_forward_ids.size();
338 int num_fdc_cands_remaining=fdctrackcandidates.size();
339 vector<int>cdc_forward_matches(cdc_forward_ids.size());
340 vector<int>cdc_backward_matches(cdc_backward_ids.size());
341
342 // Loop through the list of FDC candidates looking for matches between the
343 // CDC and the FDC in the transition region.
344 if (num_forward_cdc_cands_remaining>0){
345 for(unsigned int i=0; i<fdctrackcandidates.size(); i++){
346 // Break out if there are no forward-pointing cdc candidates that have
347 // not already been matched to fdc candidates.
348 if (num_forward_cdc_cands_remaining==0) break;
349
350 // The current FDC candidate
351 const DTrackCandidate *fdccan = fdctrackcandidates[i];
352 vector<const DFDCSegment *>segments;
353 fdccan->GetT(segments);
354 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
355 if (segments[0]->package!=0) continue;
356
357 // Flag for matching status
358 bool got_match=false;
359
360 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<360<<" "
<< "Attempting FDC/CDC matching method #1..." <<endl;
361
362 // Check that the z-position at the doca to the beam line is within the
363 // active volume of the detector to prevent connecting low momentum
364 // curlers coming off the cdc endplate at a small angle with CDC
365 // candidates
366 if (CheckZPosition(fdccan)==false){
367 // mark to avoid trying to match to CDC with the alternate
368 // matching algorithms below
369 forward_matches[i]=-1;
370 continue;
371 }
372
373 // First try the matching method that projects the cdc candidate to the
374 // cdc endplate where the fdc candidates are reported.
375 if (MatchMethod1(fdccan,cdc_forward_ids,cdc_endplate_projections,
376 cdc_forward_matches)){
377 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<377<<" "
<< "... matched to FDC candidate #" << i <<endl;
378
379 got_match=true;
380 }
381 else{
382 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<382<<" "
<< "Attempting FDC/CDC matching method #2..." <<endl;
383 // loop over the forward-pointing cdc candidates
384 for (unsigned int j=0;j<cdc_forward_ids.size();j++){
385 if (cdc_forward_matches[j]) continue;
386 const DTrackCandidate *cdccan=cdctrackcandidates[cdc_forward_ids[j]];
387
388 // Try to gather up stray CDC hits from candidates that were not
389 // matched with the previous algorithm by projecting the helical track
390 // from the fdc into the cdc region
391 if (MatchMethod2(fdccan,cdccan)){
392 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<392<<" "
<< "... matched to FDC candidate #" << i <<endl;
393 // mark the cdc candidate as matched
394 cdc_forward_matches[j]=1;
395
396 if (DEBUG_LEVEL>0)
397 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<397<<" "
<< ".. matched to CDC candidate #" <<cdc_forward_ids[j] <<endl;
398 got_match=true;
399 break;
400 }
401 }
402 }
403
404 if (got_match){
405 // Mark the FDC candidate as matched
406 forward_matches[i]=1;
407 num_fdc_cands_remaining--;
408
409 // update number of unmatched forward-pointing cdc candidates
410 num_forward_cdc_cands_remaining--;
411 }
412 } // loop over fdc candidates
413 } // check for forward-pointing cdc candidates
414
415 // If starting with the fdc candidates did not lead to a complete set of
416 // CDC-FDC matches, try looping over the remaining CDC candidates that point
417 // toward the FDC.
418 if (num_forward_cdc_cands_remaining>0){
419 for (unsigned int i=0;i<cdc_forward_ids.size();i++){
420 if (cdc_forward_matches[i]) continue;
421 if (num_forward_cdc_cands_remaining==0) break;
422
423 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<423<<" "
<< "Attempting FDC/CDC matching method #3..." <<endl;
424
425 // This method projects the cdc track into the FDC region
426 const DTrackCandidate *cdccan=cdctrackcandidates[cdc_forward_ids[i]];
427 if (MatchMethod3(cdccan,forward_matches)){
428 num_fdc_cands_remaining--;
429 num_forward_cdc_cands_remaining--;
430
431 //Mark the cdc track candidate as matched
432 cdc_forward_matches[i]=1;
433
434 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<434<<" "
<< "... matched to CDC candidate #" << i <<endl;
435 }
436 } // loop over forward-pointing cdc candidates
437 }
438
439 // The following uses a trick to improve the circle fit and "fix" the
440 // direction of a cdc candidate for those candidates whose outermost hit
441 // is a stereo straw by assuming that the z position is at the end of this
442 // straw at the cdc endplate, thereby giving us an additional point in the
443 // xy plane that can be used in the circle fit. The code then attempts to
444 // match this "improved" cdc candidate with the remaining fdc candidates.
445 if (num_fdc_cands_remaining>0 && num_forward_cdc_cands_remaining>0){
446 for (unsigned int j=0;j<cdc_forward_ids.size();j++){
447 if (num_fdc_cands_remaining==0) break;
448 if (num_forward_cdc_cands_remaining==0) break;
449 if (cdc_forward_matches[j]==0){
450 const DTrackCandidate *cdccan = cdctrackcandidates[cdc_forward_ids[j]];
451
452 if (MatchMethod8(cdccan,forward_matches)==true){
453 cdc_forward_matches[j]=1;
454 num_fdc_cands_remaining--;
455 num_forward_cdc_cands_remaining--;
456 }
457
458 }
459 }
460 }
461
462 // add to the main list of candidates those we did not successfully merge
463 if (num_forward_cdc_cands_remaining>0){
464 for (unsigned int j=0;j<cdc_forward_ids.size();j++){
465 if (cdc_forward_matches[j]==0){
466 DTrackCandidate *can = new DTrackCandidate;
467
468 const DTrackCandidate *cdccan = cdctrackcandidates[cdc_forward_ids[j]];
469 vector<const DCDCTrackHit *>cdchits;
470 cdccan->GetT(cdchits);
471
472 // circle parameters
473 can->rc=cdccan->rc;
474 can->xc=cdccan->xc;
475 can->yc=cdccan->yc;
476
477 DVector3 mom=cdccan->momentum();
478 DVector3 pos=cdccan->position();
479
480 can->setMomentum(mom);
481 can->setPosition(pos);
482 can->setPID(cdccan->PID());
483
484 for (unsigned int n=0;n<cdchits.size();n++){
485 used_cdc_hits[cdccan->used_cdc_indexes[n]]=1;
486 can->AddAssociatedObject(cdchits[n]);
487 }
488 can->chisq=cdccan->chisq;
489 can->Ndof=cdccan->Ndof;
490 trackcandidates.push_back(can);
491 }
492 }
493 }
494
495 for (unsigned int j=0;j<cdc_backward_ids.size();j++){
496 const DTrackCandidate *cdccan = cdctrackcandidates[cdc_backward_ids[j]];
497
498 // Sometimes the cdc track candidate parameters for tracks that are actually
499 // going forward are so poor that they don't seem to point towards the cdc
500 // end plate, so the previous matching methods fail. Try one more time
501 // to match these to FDC segments by using Method 8...
502 if (num_fdc_cands_remaining>0
503 && MatchMethod8(cdccan,forward_matches)==true){
504 num_fdc_cands_remaining--;
505 cdc_backward_matches[j]=1;
506 }
507 else{
508 DVector3 mom=cdccan->momentum();
509 DVector3 pos=cdccan->position();
510
511 // Check for candidates that appear to go backwards but are actually
512 // going forwards and try to match these to remaining fdc candidates
513 if (num_fdc_cands_remaining>0 && mom.Theta()>M_PI_21.57079632679489661923 && !sc_pos.empty()){
514 if (TryToFlipDirection(schits,mom,pos)){
515 if (DEBUG_LEVEL>0){
516 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<516<<" "
<< "Flipped direction of track (backward to forward) to look for FDC match..." << endl;
517 }
518 DVector3 norm(0.,0.,1.);
519 double p_cdc=mom.Mag();
520 stepper->SetCharge(cdccan->charge());
521 stepper->SwimToPlane(pos,mom,cdc_endplate,norm,NULL__null);
522
523 for (unsigned int i=0;i<fdctrackcandidates.size();i++){
524 if (num_fdc_cands_remaining==0) break;
525 if (forward_matches[i]==0){
526 const DTrackCandidate *fdccan=fdctrackcandidates[i];
527 if (MatchMethod2(fdccan,cdccan)){
528 if (DEBUG_LEVEL>0) {
529 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<529<<" "
<< "... matched to FDC candidate #" << i <<endl;
530 }
531 forward_matches[i]=1;
532 cdc_backward_matches[j]=1;
533 num_fdc_cands_remaining--;
534 break;
535 }
536
537 // Use MatchMethod1 if the previous method did not work
538 DVector3 fdcpos=fdccan->position();
539 DVector3 fdcmom=fdccan->momentum();
540 double p_fdc=fdcmom.Mag();
541 ProjectHelixToZ(cdc_endplate.z(),fdccan->charge(),fdcmom,fdcpos);
542 double diff=(pos-fdcpos).Mag();
543 if (cdc_fdc_match(p_fdc,p_cdc,diff)){
544 // Get the segment data
545 vector<const DFDCSegment *>segments;
546 fdccan->GetT(segments);
547
548 // The following code snippet is intended to prevent matching a cdc
549 // track candidate to a low momentum particle curling from the cdc endplate
550 double theta=fdcmom.Theta();
551 if (segments.size()>1 && p_fdc<0.3 && theta< 5.*M_PI3.14159265358979323846/180.){
552 continue;
553 }
554
555 if (MakeCandidateFromMethod1(theta,segments,cdccan)){
556 forward_matches[i]=1;
557 num_fdc_cands_remaining--;
558 cdc_backward_matches[j]=1;
559 if (DEBUG_LEVEL>0)
560 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<560<<" "
<< ".. matched to CDC candidate #" << cdc_backward_ids[j] <<endl;
561 break;
562 }
563 } // match criterion met?
564 } // fdc candidate not already matched?
565 } // loop over fdc candidates
566 }
567 } // do we have fdc candidates remaining?
568 }
569 } //loop over "backward" going cdc tracks
570
571 // put the remaining "backward" tracks in the main list of candidates
572 for (unsigned int j=0;j<cdc_backward_ids.size();j++){
573 if (cdc_backward_matches[j]==0){
574 const DTrackCandidate *cdccan = cdctrackcandidates[cdc_backward_ids[j]];
575
576 // Get the cdc hits
577 vector<const DCDCTrackHit *>cdchits;
578 cdccan->GetT(cdchits);
579 stable_sort(cdchits.begin(), cdchits.end(), CDCHitSortByLayerincreasing);
580
581 DTrackCandidate *can = new DTrackCandidate;
582 can->setMomentum(cdccan->momentum());
583 can->setPosition(cdccan->position());
584 can->setPID(cdccan->PID());
585
586 // circle parameters
587 can->rc=cdccan->rc;
588 can->xc=cdccan->xc;
589 can->yc=cdccan->yc;
590
591 for (unsigned int n=0;n<cdchits.size();n++){
592 can->AddAssociatedObject(cdchits[n]);
593 }
594 can->chisq=cdccan->chisq;
595 can->Ndof=cdccan->Ndof;
596
597 trackcandidates.push_back(can);
598 }
599 }
600
601 // If there are more than one FDC candidates remaining, use the best track
602 // candidate knowledge we have so far to recheck for matches to other fdc
603 // candidates.
604 if (num_fdc_cands_remaining>1){
605 for (unsigned int j=0;j<fdctrackcandidates.size();j++){
606 if (num_fdc_cands_remaining<1) break;
607 if (forward_matches[j]<=0){
608 // Try to match to fdc candidates that have not already been matched
609 // to another track
610 if (MatchMethod4(fdctrackcandidates[j],forward_matches,num_fdc_cands_remaining)==true){
611 forward_matches[j]=1;
612 num_fdc_cands_remaining--;
613 }
614 }
615 }
616 }
617
618 // Of the remaining fdc candidates, output those that have more than one
619 // segment associated with them.
620 if (num_fdc_cands_remaining>0){
621 for (unsigned int j=0;j<fdctrackcandidates.size();j++){
622 if (forward_matches[j]<=0){
623 const DTrackCandidate *fdccan = fdctrackcandidates[j];
624
625 // Get the segment data
626 vector<const DFDCSegment *>segments;
627 fdccan->GetT(segments);
628
629 if (segments.size()>1){
630 // Create new candidate for output
631 DTrackCandidate *can = new DTrackCandidate;
632 // circle parameters
633 can->rc=fdccan->rc;
634 can->xc=fdccan->xc;
635 can->yc=fdccan->yc;
636
637 can->setMomentum(fdccan->momentum());
638 can->setPosition(fdccan->position());
639 can->setPID(fdccan->PID());
640 can->chisq=fdccan->chisq;
641 can->Ndof=fdccan->Ndof;
642 for (unsigned int m=0;m<segments.size();m++){
643 for (unsigned int n=0;n<segments[m]->hits.size();n++){
644 const DFDCPseudo *fdchit=segments[m]->hits[n];
645 can->AddAssociatedObject(fdchit);
646 }
647 }
648 trackcandidates.push_back(can);
649
650 num_fdc_cands_remaining--;
651 forward_matches[j]=1;
652 }
653 }
654 }
655 }
656
657 // Try to match remaining fdc candidates to track candidates that have
658 // track segments that have already been matched together
659 if (num_fdc_cands_remaining>0){
660 vector<int>candidate_updated(trackcandidates.size());
661 for (unsigned int i=0;i<trackcandidates.size();i++){
662 if (num_fdc_cands_remaining<=0) break;
663
664 DTrackCandidate *can=trackcandidates[i];
665 if (MatchMethod7(can,forward_matches,num_fdc_cands_remaining)==false){
666 if (can->momentum().Mag()<0.5){
667 if (MatchMethod12(can,forward_matches,num_fdc_cands_remaining)){
668 candidate_updated[i]=1;
669 }
670 }
671 }
672 }
673 if (num_fdc_cands_remaining>0){
674 // if the candidate was updated, try again...
675 for (unsigned int i=0;i<trackcandidates.size();i++){
676 if (num_fdc_cands_remaining==0) break;
677 if (candidate_updated[i]==1){
678 DTrackCandidate *can=trackcandidates[i];
679 if (MatchMethod7(can,forward_matches,num_fdc_cands_remaining)==false){
680 if (can->momentum().Mag()<0.5){
681 MatchMethod12(can,forward_matches,num_fdc_cands_remaining);
682 }
683 }
684 }
685 }
686 }
687 }
688
689 // We should be left with only single-segment fdc candidates. We try to
690 // connect them together using alternate fitting techniques, either by
691 // forcing the circle to originate from the target or at the other extreme
692 // not including the fake point at the origin.
693 if (num_fdc_cands_remaining){
694 bool matched_stray_segments=MatchStraySegments(forward_matches,
695 num_fdc_cands_remaining);
696 if (num_fdc_cands_remaining && matched_stray_segments){
697 for (unsigned int i=0;i<trackcandidates.size();i++){
698 if (num_fdc_cands_remaining==0) break;
699
700 DTrackCandidate *can=trackcandidates[i];
701 if (MatchMethod7(can,forward_matches,num_fdc_cands_remaining)==false){
702 if (can->momentum().Mag()<0.5){
703 MatchMethod12(can,forward_matches,num_fdc_cands_remaining);
704 }
705 }
706 }
707 }
708 if (num_fdc_cands_remaining){
709 // Not much we can do here -- add to the final list of candidates
710 for (unsigned int j=0;j<forward_matches.size();j++){
711 if (num_fdc_cands_remaining==0) break;
712 if (forward_matches[j]<=0){
713 const DTrackCandidate *srccan=fdctrackcandidates[j];
714 // Get the segment data
715 vector<const DFDCSegment *>segments;
716 srccan->GetT(segments);
717 const DFDCSegment *segment=segments[0];
718
719 DTrackCandidate *can = new DTrackCandidate;
720 // circle parameters
721 can->rc=srccan->rc;
722 can->xc=srccan->xc;
723 can->yc=srccan->yc;
724
725 can->Ndof=srccan->Ndof;
726 can->chisq=srccan->chisq;
727 can->setPID(srccan->PID());
728 can->setMomentum(srccan->momentum());
729 can->setPosition(srccan->position());
730 for (unsigned int n=0;n<segment->hits.size();n++){
731 const DFDCPseudo *fdchit=segment->hits[n];
732 can->AddAssociatedObject(fdchit);
733 }
734
735 trackcandidates.push_back(can);
736 }
737 }
738 }
739 }
740
741 //There are frequently several hits in the CDC that are not associated with
742 // any track segment. In this case, try to attach these stray hits to a
743 // track in the FDC that has hits in the first package.
744 if (num_unmatched_cdcs>0){
745 if (DEBUG_LEVEL>0){
746 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<746<<" "
<< "Trying to use stray CDC hits in match to FDC..." << endl;
747 }
748
749 for (unsigned int i=0;i<trackcandidates.size();i++){
750 if (num_unmatched_cdcs>0){
751 DTrackCandidate *candidate=trackcandidates[i];
752 // Get the hits from the candidate
753 vector<const DCDCTrackHit *>usedcdchits;
754 candidate->GetT(usedcdchits);
755 if (usedcdchits.size()==0){
756 vector<const DFDCPseudo*>usedfdchits;
757 candidate->GetT(usedfdchits);
758 // Sort the hits
759 stable_sort(usedfdchits.begin(),usedfdchits.end(),FDCHitSortByLayerincreasing);
760 if ((usedfdchits[0]->wire->layer-1)/6==0){
761 MatchMethod6(candidate,usedfdchits,used_cdc_hits,num_unmatched_cdcs);
762 }
763 }
764 }
765 }
766 }
767
768 // Only output the candidates that have at least a minimum number of hits
769 for (unsigned int i=0;i<trackcandidates.size();i++){
770 DTrackCandidate *candidate=trackcandidates[i];
771 // Get the hits from the candidate
772 vector<const DFDCPseudo*>myfdchits;
773 candidate->GetT(myfdchits);
774 vector<const DCDCTrackHit *>mycdchits;
775 candidate->GetT(mycdchits);
776
777 if (mycdchits.size()>=3 || myfdchits.size()>=3){
778 _data.push_back(candidate);
779 }
780 else delete candidate;
781 }
782
783 if((int(_data.size()) > MAX_NUM_TRACK_CANDIDATES) && (MAX_NUM_TRACK_CANDIDATES >= 0))
784 {
785 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<785<<" "
<< "Number of candidates = " << _data.size()
786 << " > " << MAX_NUM_TRACK_CANDIDATES
787 << " --- skipping track fitting! " << endl;
788 for(size_t loc_i = 0; loc_i < _data.size(); ++loc_i)
789 delete _data[loc_i];
790 _data.clear();
791 }
792
793
794 // Set CDC ring & FDC plane hit patterns
795 for(size_t loc_i = 0; loc_i < _data.size(); ++loc_i)
796 {
797 vector<const DCDCTrackHit*> locCDCTrackHits;
798 _data[loc_i]->Get(locCDCTrackHits);
799
800 vector<const DFDCPseudo*> locFDCPseudos;
801 _data[loc_i]->Get(locFDCPseudos);
802
803 _data[loc_i]->dCDCRings = dParticleID->Get_CDCRingBitPattern(locCDCTrackHits);
804 _data[loc_i]->dFDCPlanes = dParticleID->Get_FDCPlaneBitPattern(locFDCPseudos);
805 }
806
807 return NOERROR;
808}
809
810
811// Obtain position and momentum at the exit of a given package using the
812// helical track model.
813void DTrackCandidate_factory::GetPositionAndMomentum(const DFDCSegment *segment,
814 DVector3 &pos,
815 DVector3 &mom) const{
816 // Position of track segment at last hit plane of package
817 double x=segment->xc+segment->rc*cos(segment->Phi1);
818 double y=segment->yc+segment->rc*sin(segment->Phi1);
819 double z=segment->hits[0]->wire->origin.z();
820
821 // Track parameters
822 //double kappa=segment->q/(2.*segment->rc);
823 double phi0=segment->phi0;
824 double tanl=segment->tanl;
825 double z0=segment->z_vertex;
826
827 // Useful intermediate variables
828 double cosp=cos(phi0);
829 double sinp=sin(phi0);
830 double sperp=(z-z0)/tanl;
831 //double twoks=2.*kappa*sperp;
832 double twoks=FactorForSenseOfRotation*segment->q*sperp/segment->rc;
833 double sin2ks=sin(twoks);
834 double cos2ks=cos(twoks);
835
836 // Get Bfield
837 double B=fabs(bfield->GetBz(x,y,z));
838
839 // Momentum
840 double pt=0.003*B*segment->rc;
841 double px=pt*(cosp*cos2ks-sinp*sin2ks);
842 double py=pt*(sinp*cos2ks+cosp*sin2ks);
843 double pz=pt*tanl;
844
845 pos.SetXYZ(x,y,z);
846 mom.SetXYZ(px,py,pz);
847}
848
849// Get position and momentum at doca to beam line
850void DTrackCandidate_factory::GetPositionAndMomentum(const DHelicalFit &fit,
851 double Bz,
852 DVector3 &pos,
853 DVector3 &mom) const{
854 // Find position at doca to beam line
855 double phi0=atan2(-fit.x0,fit.y0);
856 if (fit.h<0) phi0+=M_PI3.14159265358979323846;
857 double sinphi0=sin(phi0);
858 double sign=(sinphi0>0)?1.:-1.;
859 if (fabs(sinphi0)<1e-8) sinphi0=sign*1e-8;
860 double cosphi0=cos(phi0);
861 double D=FactorForSenseOfRotation*fit.h*fit.r0-fit.x0/sinphi0;
862 double x=-D*sinphi0;
863 double y=D*cosphi0;
864 double dx=pos.x()-x;
865 double dy=pos.y()-y;
866 double ratio=sqrt(dx*dx+dy*dy)/(2.*fit.r0);
867 double phi_s=(ratio<1.)?2.*asin(ratio):M_PI3.14159265358979323846;
868 double newz=pos.z()-phi_s*fit.tanl*fit.r0;
869 pos.SetXYZ(x,y,newz);
870
871 // momentum at POCA to beam line
872 double pt=0.003*Bz*fit.r0;
873 mom.SetXYZ(pt*cosphi0,pt*sinphi0,pt*fit.tanl);
874}
875
876// Get the position and momentum at a fixed radius from the beam line
877jerror_t DTrackCandidate_factory::GetPositionAndMomentum(DHelicalFit &fit,
878 double Bz,
879 const DVector3 &origin,
880 DVector3 &pos,
881 DVector3 &mom) const{
882 double r2=90.0;
883 double xc=fit.x0;
884 double yc=fit.y0;
885 double rc=fit.r0;
886 double tworc=2.*rc;
887 double rc2=rc*rc;
888 double xc2=xc*xc;
889 double yc2=yc*yc;
890 double xc2_plus_yc2=xc2+yc2;
891 double a=(r2-xc2_plus_yc2-rc2)/tworc;
892 double b=xc2_plus_yc2-a*a;
893 if (b<0){
894 // We did not find an intersection between the two circles, so return
895 // an error. The values of mom and pos are not changed.
896 return VALUE_OUT_OF_RANGE;
897 }
898
899 double temp1=yc*sqrt(b);
900 double temp2=xc*a;
901 double cosphi_plus=(temp2+temp1)/xc2_plus_yc2;
902 double cosphi_minus=(temp2-temp1)/xc2_plus_yc2;
903
904 // Direction tangent and transverse momentum
905 double tanl=fit.tanl;
906 double pt=0.003*Bz*rc;
907
908 double phi_plus=acos(cosphi_plus);
909 double phi_minus=acos(cosphi_minus);
910 double x_plus=xc+rc*cosphi_plus;
911 double x_minus=xc+rc*cosphi_minus;
912 double y_plus=yc+rc*sin(phi_plus);
913 double y_minus=yc+rc*sin(phi_minus);
914
915 // if the resulting radial position on the circle from the fit does not agree
916 // with the radius to which we are matching, we have the wrong sign for phi+
917 // or phi-
918 double r2_plus=x_plus*x_plus+y_plus*y_plus;
919 double r2_minus=x_minus*x_minus+y_minus*y_minus;
920 if (fabs(r2-r2_plus)>EPS0.001){
921 phi_plus*=-1.;
922 y_plus=yc+rc*sin(phi_plus);
923 }
924 if (fabs(r2-r2_minus)>EPS0.001){
925 phi_minus*=-1.;
926 y_minus=yc+rc*sin(phi_minus);
927 }
928
929 // Choose phi- or phi+ depending on proximity to one of the cdc hits
930 double xwire=origin.x();
931 double ywire=origin.y();
932 double dx=x_minus-xwire;
933 double dy=y_minus-ywire;
934 double d2_minus=dx*dx+dy*dy;
935 dx=x_plus-xwire;
936 dy=y_plus-ywire;
937 double d2_plus=dx*dx+dy*dy;
938
939 DVector3 pos0(pos); // save the input position, for use in finding z
940 if (d2_plus>d2_minus){
941 fit.h=-1.;
942 phi_minus=M_PI3.14159265358979323846-phi_minus;
943 pos.SetXYZ(x_minus,y_minus,0.); // z will be filled later
944 mom.SetXYZ(pt*sin(phi_minus),pt*cos(phi_minus),pt*tanl);
945 }
946 else{
947 fit.h=1.;
948 phi_plus*=-1.;
949 pos.SetXYZ(x_plus,y_plus,0.); // z will be filled later
950 mom.SetXYZ(pt*sin(phi_plus),pt*cos(phi_plus),pt*tanl);
951 }
952 // Next find the z-position corresponding to the new (x,y) position
953 double ratio=(pos0-pos).Perp()/tworc;
954 double sperp=(ratio<1.)?tworc*asin(ratio):tworc*M_PI_21.57079632679489661923;
955 pos.SetZ(pos0.z()-sperp*tanl);
956
957 return NOERROR;
958}
959
960// Find the position along a helical path at the z-position z
961void DTrackCandidate_factory::ProjectHelixToZ(const double z,const double q,
962 const DVector3 &mom,
963 DVector3 &pos){
964 double pt=mom.Perp();
965 double phi=mom.Phi();
966 double sinphi=sin(phi);
967 double cosphi=cos(phi);
968 double tanl=tan(M_PI_21.57079632679489661923-mom.Theta());
969 double x0=pos.X();
970 double y0=pos.Y();
971 double z0=pos.Z();
972 double B=fabs(bfield->GetBz(x0,y0,z0));
973 double twokappa=FactorForSenseOfRotation*0.003*B*q/pt;
974 double one_over_twokappa=1./twokappa;
975 double sperp=(z-z0)/tanl;
976 double twoks=twokappa*sperp;
977 double sin2ks=sin(twoks);
978 double one_minus_cos2ks=1.-cos(twoks);
979 double x=x0+(cosphi*sin2ks-sinphi*one_minus_cos2ks)*one_over_twokappa;
980 double y=y0+(sinphi*sin2ks+cosphi*one_minus_cos2ks)*one_over_twokappa;
981
982 pos.SetXYZ(x,y,z);
983}
984
985
986// Routine to do a crude match between cdc wires and a helical approximation to
987// the trajectory
988double DTrackCandidate_factory::DocaToHelix(const DCDCTrackHit *hit,
989 double q,
990 const DVector3 &pos,
991 const DVector3 &mom){
992 double pt=mom.Perp();
993 double phi=mom.Phi();
994 double sinphi=sin(phi);
995 double cosphi=cos(phi);
996 double tanl=tan(M_PI_21.57079632679489661923-mom.Theta());
997 double x0=pos.X();
998 double y0=pos.Y();
999 double z0=pos.Z();
1000 // _DBG_ <<endl;
1001 double B=fabs(bfield->GetBz(x0,y0,z0));
1002 double twokappa=FactorForSenseOfRotation*0.003*B*q/pt;
1003 double one_over_twokappa=1./twokappa;
1004
1005 double sperp=0;
1006 DVector3 origin=hit->wire->origin;
1007 double z0w=origin.z();
1008 DVector3 dir=(1./hit->wire->udir.z())*hit->wire->udir;
1009
1010 DVector3 wirepos;
1011 double old_doca2=1e8;
1012 double doca2=old_doca2;
1013 double z=z0;
1014 double x=x0,y=y0;
1015 while (z>50. && z<180. && x<60. && y<60.){
1016 old_doca2=doca2;
1017 sperp-=1.;
1018 double twoks=twokappa*sperp;
1019 double sin2ks=sin(twoks);
1020 double one_minus_cos2ks=1.-cos(twoks);
1021 x=x0+(cosphi*sin2ks-sinphi*one_minus_cos2ks)*one_over_twokappa;
1022 y=y0+(sinphi*sin2ks+cosphi*one_minus_cos2ks)*one_over_twokappa;
1023 z=z0+sperp*tanl;
1024
1025 wirepos=origin+(z-z0w)*dir;
1026 double dxw=x-wirepos.x();
1027 double dyw=y-wirepos.y();
1028
1029 doca2=dxw*dxw+dyw*dyw;
1030 if (doca2>old_doca2){
1031 break;
1032 }
1033 }
1034
1035 return old_doca2;
1036}
1037
1038
1039// Find the particle charge given the helical fit result and an fdc hit
1040// on the track
1041double DTrackCandidate_factory::GetSenseOfRotation(DHelicalFit &fit,
1042 const DFDCPseudo *fdchit,
1043 const DVector3 &pos
1044 ){
1045 // Get circle parameters
1046 double rc=fit.r0;
1047 double xc=fit.x0;
1048 double yc=fit.y0;
1049 // Compute phi rotation from "vertex" to fdc hit
1050 double dphi=(fdchit->wire->origin.Z()-pos.z())/(rc*fit.tanl);
1051 double Phi1=atan2(pos.Y()-yc,pos.X()-xc);
1052
1053 // Positive and negative changes in phi
1054 double phiplus=Phi1+dphi;
1055 double phiminus=Phi1-dphi;
1056 DVector2 plus(xc+rc*cos(phiplus),yc+rc*sin(phiplus));
1057 DVector2 minus(xc+rc*cos(phiminus),yc+rc*sin(phiminus));
1058
1059 // Compute differences
1060 double d2plus=(plus-fdchit->xy).Mod2();
1061 double d2minus=(minus-fdchit->xy).Mod2();
1062
1063 if (d2minus<d2plus)
1064 return (-1.0);
1065 else
1066 return (+1.0);
1067}
1068
1069
1070
1071// Redo the circle fit using all of the cdc axial wires and fdc hits associated
1072// with the track candidate. Also compute the average Bz.
1073jerror_t DTrackCandidate_factory::DoRefit(DHelicalFit &fit,
1074 vector<const DFDCSegment *>segments,
1075 vector<const DCDCTrackHit *>cdchits,
1076 double &Bz){
1077 unsigned int num_hits=0;
1078 // Initialize Bz
1079 Bz=0.;
1080
1081 // Add the cdc axial wires to the list of hits to use in the fit
1082 for (unsigned int k=0;k<cdchits.size();k++){
1083 if (cdchits[k]->is_stereo==false){
1084 double cov=0.213; //guess
1085 const DVector3 origin=cdchits[k]->wire->origin;
1086 double x=origin.x(),y=origin.y(),z=origin.z();
1087 fit.AddHitXYZ(x,y,z,cov,cov,0.,true);
1088 Bz+=bfield->GetBz(x,y,z);
1089 num_hits++;
1090 }
1091 }
1092 // Add the FDC hits and estimate Bz
1093 for (unsigned int k=0;k<segments.size();k++){
1094 for (unsigned int n=0;n<segments[k]->hits.size();n++){
1095 const DFDCPseudo *fdchit=segments[k]->hits[n];
1096 fit.AddHit(fdchit);
1097 //bfield->GetField(x,y,z,Bx,By,Bz);
1098 //Bz_avg-=Bz;
1099 Bz+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),fdchit->wire->origin.z());
1100 }
1101 num_hits+=segments[k]->hits.size();
1102 }
1103 Bz=fabs(Bz)/double(num_hits);
1104
1105 // Fit the points to a circle
1106 if (fit.FitCircleRiemann(segments[0]->rc)==NOERROR){
1107 double p=0.003*Bz*fit.r0/cos(atan(fit.tanl));
1108
1109 if (p>3.){ // momentum is suspiciously high for a track going through both
1110 // the FDC and the CDC... try alternate circle fit...
1111 fit.FitCircle();
1112 }
1113 return NOERROR;
1114 }
1115
1116 return RESOURCE_UNAVAILABLE;
1117}
1118
1119// Method to match FDC and CDC candidates that projects the CDC candidate to the
1120// cdc endplate, where the FDC candidates are reported.
1121bool DTrackCandidate_factory::MatchMethod1(const DTrackCandidate *fdccan,
1122 vector<unsigned int> &cdc_forward_ids,
1123 vector<DVector3>&cdc_endplate_projections,
1124 vector<int>&cdc_forward_matches
1125 ){
1126 // Momentum and position vectors for the FDC candidate
1127 DVector3 mom=fdccan->momentum();
1128 DVector3 pos=fdccan->position();
1129 double p_fdc=mom.Mag();
1130 ProjectHelixToZ(cdc_endplate.z(),fdccan->charge(),mom,pos);
1131
1132 // loop over the cdc candidates looking for the smallest distance
1133 // between the cdc and fdc projections to the end plate
1134 double diff_min=1000.; // candidate matching difference
1135 unsigned int jmin=0;
1136 for (unsigned int j=0;j<cdc_forward_ids.size();j++){
1137 if (cdc_forward_matches[j]) continue;
1138 double diff=(cdc_endplate_projections[j]-pos).Mag();
1139 if (diff<diff_min){
1140 diff_min=diff;
1141 jmin=j;
1142 }
1143 }
1144
1145 if (DEBUG_HISTS){
1146 match_dist->Fill(pos.Perp(),diff_min);
1147 match_dist_vs_p->Fill(p_fdc,diff_min);
1148 }
1149
1150 // Magnitude of the momentum of the potential cdc match
1151 double p_cdc=cdctrackcandidates[cdc_forward_ids[jmin]]->momentum().Mag();
1152 if (cdc_fdc_match(p_fdc,p_cdc,diff_min)){
1153 // Get the segment data
1154 vector<const DFDCSegment *>segments;
1155 fdccan->GetT(segments);
1156
1157 // The following code snippet is intended to prevent matching a cdc
1158 // track candidate to a low momentum particle curling from the cdc endplate
1159 if (segments.size()>1){
1160 double theta=180./M_PI3.14159265358979323846*mom.Theta();
1161 if (p_fdc<0.3 && theta<5.) return false;
1162 }
1163
1164 unsigned int cdc_index=cdc_forward_ids[jmin];
1165 if (MakeCandidateFromMethod1(mom.Theta(),segments,
1166 cdctrackcandidates[cdc_index])){
1167
1168 if (DEBUG_LEVEL>0)
1169 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1169<<" "
<< ".. matched to CDC candidate #" << cdc_index <<endl;
1170
1171 // mark the cdc candidate as matched
1172 cdc_forward_matches[jmin]=1;
1173
1174 return true;
1175 }
1176 } // got a cdc-fdc match
1177
1178 // no match
1179 return false;
1180}
1181
1182// Create new candidate after using Match Method 1 to match cdc and fdc
1183// candidates
1184bool DTrackCandidate_factory::MakeCandidateFromMethod1(double theta,vector<const DFDCSegment *>&segments,const DTrackCandidate *cdccan){
1185 // JANA does not maintain the order that the segments were added
1186 // as associated objects. Therefore, we need to reorder them here
1187 // so segment[0] is the most upstream segment.
1188 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
1189
1190 // Get the associated cdc hits
1191 vector<const DCDCTrackHit *>cdchits;
1192 cdccan->GetT(cdchits);
1193
1194 // Sort CDC hits by layer
1195 stable_sort(cdchits.begin(), cdchits.end(), CDCHitSortByLayerincreasing);
1196
1197 // Abort if the track would have to pass from one quadrant into another
1198 // quadrant (this is more likely two roughly back-to-back tracks rather than
1199 // a single track).
1200 const DVector2 fdc_hit_pos=segments[0]->hits[0]->xy;
1201 const DVector3 cdc_wire_origin=cdchits[0]->wire->origin;
1202 if (cdc_wire_origin.x()*fdc_hit_pos.X()<0.
1203 || cdc_wire_origin.y()*fdc_hit_pos.Y()<0.){
1204 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1204<<" "
<< "Skipping match of potential back-to-back tracks." <<endl;
1205 return false;
1206 }
1207
1208 // average Bz
1209 double Bz_avg=0.;
1210
1211 // Redo circle fit with additional hits
1212 DHelicalFit fit;
1213 if (DoRefit(fit,segments,cdchits,Bz_avg)==NOERROR){
1214 // Determine the polar angle
1215 double theta_cdc=cdccan->momentum().Theta();
1216 if (segments.size()==1 && theta_cdc<M_PI_40.78539816339744830962){
1217 double numcdc=double(cdchits.size());
1218 double numfdc=segments[0]->hits.size();
1219 theta=(theta*numfdc+theta_cdc*numcdc)/(numfdc+numcdc);
1220 }
1221 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
1222
1223 // FDC hit
1224 const DFDCPseudo *fdchit=segments[0]->hits[0];
1225 double zhit=fdchit->wire->origin.z();
1226 DVector3 pos(fdchit->xy.X(),fdchit->xy.Y(),zhit);
1227 DVector3 mom;
1228 UpdatePositionAndMomentum(fit,Bz_avg,cdchits[0]->wire->origin,pos,mom);
1229
1230 // Create new track candidate object
1231 DTrackCandidate *can = new DTrackCandidate;
1232 can->used_cdc_indexes=cdccan->used_cdc_indexes;
1233 // circle parameters
1234 can->rc=fit.r0;
1235 can->xc=fit.x0;
1236 can->yc=fit.y0;
1237
1238 // Add cdc and fdc hits to the track as associated objects
1239 for (unsigned int m=0;m<segments.size();m++){
1240 for (unsigned int n=0;n<segments[m]->hits.size();n++){
1241 can->AddAssociatedObject(segments[m]->hits[n]);
1242 }
1243 }
1244 for (unsigned int n=0;n<cdchits.size();n++){
1245 can->AddAssociatedObject(cdchits[n]);
1246 }
1247
1248 can->chisq=fit.chisq;
1249 can->Ndof=fit.ndof;
1250 Particle_t locPID = (FactorForSenseOfRotation*fit.h > 0.0) ? PiPlus : PiMinus;
1251 can->setPID(locPID);
1252 can->setMomentum(mom);
1253 can->setPosition(pos);
1254
1255 trackcandidates.push_back(can);
1256
1257 return true;
1258 }
1259 return false;
1260}
1261
1262// Method to match CDC and FDC candidates that projects an FDC candidate into
1263// the CDC region using a helical approximation to the trajectory. The code
1264// computes a doca to each wire in the cdc candidate and counts matches based
1265// on the probability that the cdc wire is on the track.
1266 bool DTrackCandidate_factory::MatchMethod2(const DTrackCandidate *fdccan,
1267 const DTrackCandidate *cdccan
1268 ){
1269 // Get the cdc hits associated with this cdc candidate
1270 vector<const DCDCTrackHit *>cdchits;
1271 cdccan->GetT(cdchits);
1272 stable_sort(cdchits.begin(),cdchits.end(),CDCHitSortByLayerincreasing);
1273
1274 // Variables to count the number of matching hits and the match fraction
1275 unsigned int num_match=0;
1276 unsigned int num_cdc=0;
1277
1278 // Get the track parameters from the fdc candidate
1279 DVector3 pos=fdccan->position();
1280 DVector3 mom=fdccan->momentum();
1281 double q=fdccan->charge();
1282
1283 // Check to see if the outer hit in the CDC does not exceed the radius of
1284 // the FDC position to try to avoid false matches...
1285 unsigned int outer_index=cdchits.size()-1;
1286 DVector3 origin=cdchits[outer_index]->wire->origin;
1287 DVector3 dir=(1./cdchits[outer_index]->wire->udir.z())*cdchits[outer_index]->wire->udir;
1288 DVector3 cdc_outer_wire_pos=origin+(167.-origin.z())*dir;
1289 if (cdc_outer_wire_pos.Perp()>pos.Perp()) {
1290 return false;
1291 }
1292 // Make sure that the rough position of the CDC track at the end plate
1293 // is not too far off from the position of the fdc track near the end plate
1294 if ((cdc_outer_wire_pos-pos).Mag()>5.){
1295 return false;
1296 }
1297
1298 // loop over the cdc hits and count hits that agree with a projection of
1299 // the helix into the cdc
1300 for (unsigned int m=0;m<cdchits.size();m++){
1301 double variance=1.6;
1302 // Use a helical approximation to the track to match both axial and
1303 // stereo wires
1304 double dr2=DocaToHelix(cdchits[m],q,pos,mom);
1305 double prob=isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
1306
1307 if (prob>0.01) num_match++;
1308 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1308<<" "
<< "CDC s: " << cdchits[m]->wire->straw
1309 << " r: " << cdchits[m]->wire->ring
1310 << " prob: " << prob << endl;
1311
1312 num_cdc++;
1313 }
1314
1315 if (num_match>=3 && double(num_match)/double(num_cdc)>0.33){
1316 // Get the segment data
1317 vector<const DFDCSegment *>segments;
1318 fdccan->GetT(segments);
1319
1320 // JANA does not maintain the order that the segments were added
1321 // as associated objects. Therefore, we need to reorder them here
1322 // so segment[0] is the most upstream segment.
1323 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
1324
1325 // Abort if the track would have to pass from one quadrant into the opposite
1326 // quadrant (this is more likely two roughly back-to-back tracks rather than
1327 // a single track).
1328 const DVector2 fdc_hit_pos=segments[0]->hits[0]->xy;
1329 const DVector3 cdc_wire_origin=cdchits[0]->wire->origin;
1330 if (cdc_wire_origin.x()*fdc_hit_pos.X()<0.
1331 && cdc_wire_origin.y()*fdc_hit_pos.Y()<0.){
1332 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1332<<" "
<< "Skipping match of potential back-to-back tracks." <<endl;
1333 return false;
1334 }
1335
1336 // Put the fdc candidate in the combined list
1337 DTrackCandidate *can = new DTrackCandidate;
1338 can->setPID((q > 0.0) ? PiPlus : PiMinus);
1339
1340 // copy the list of cdc indices over from the cdc candidate
1341 can->used_cdc_indexes=cdccan->used_cdc_indexes;
1342
1343 // Add the fdc hits to track candidate as associated objects
1344 unsigned int num_fdc_hits=0;
1345 for (unsigned int m=0;m<segments.size();m++){
1346 for (unsigned int n=0;n<segments[m]->hits.size();n++){
1347 can->AddAssociatedObject(segments[m]->hits[n]);
1348 num_fdc_hits++;
1349 }
1350 }
1351 // Add the CDC hits to the track candidate
1352 for (unsigned int m=0;m<cdchits.size();m++){
1353 can->AddAssociatedObject(cdchits[m]);
1354 }
1355
1356 // Average Bz
1357 double Bz_avg=0.;
1358
1359 // Redo circle fit with additional hits
1360 DHelicalFit fit;
1361 //...first add the tangent to the dip angle to the fit class...
1362 double theta=fdccan->momentum().Theta();
1363 double theta_cdc=cdccan->momentum().Theta();
1364 if (segments.size()==1&& theta_cdc<M_PI_40.78539816339744830962){
1365 double numcdc=double(cdchits.size());
1366 double numfdc=segments[0]->hits.size();
1367 theta=(theta*numfdc+theta_cdc*numcdc)/(numfdc+numcdc);
1368 }
1369 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
1370 if (DoRefit(fit,segments,cdchits,Bz_avg)==NOERROR){
1371 fit.FindSenseOfRotation();
1372 Particle_t locPID = ((FactorForSenseOfRotation*fit.h > 0.0) ? PiPlus : PiMinus);
1373 can->setPID(locPID);
1374
1375 // FDC hit
1376 const DFDCPseudo *fdchit=segments[0]->hits[0];
1377 double zhit=fdchit->wire->origin.z();
1378 pos.SetXYZ(fdchit->xy.X(),fdchit->xy.Y(),zhit);
1379 UpdatePositionAndMomentum(fit,Bz_avg,cdchits[0]->wire->origin,pos,mom);
1380
1381 // circle parameters
1382 can->rc=fit.r0;
1383 can->xc=fit.x0;
1384 can->yc=fit.y0;
1385
1386 can->chisq=fit.chisq;
1387 can->Ndof=fit.ndof;
1388 can->setMomentum(mom);
1389 can->setPosition(pos);
1390 }
1391 else{
1392 //_DBG_ << endl;
1393 // circle parameters
1394 can->rc=fdccan->rc;
1395 can->xc=fdccan->xc;
1396 can->yc=fdccan->yc;
1397 can->Ndof=fdccan->Ndof;
1398 can->chisq=fdccan->chisq;
1399 can->setMomentum(fdccan->momentum());
1400 can->setPosition(fdccan->position());
1401 }
1402
1403 trackcandidates.push_back(can);
1404
1405 return true;
1406 }
1407
1408 return false;
1409 }
1410
1411 // Method to match CDC and FDC candidates that projects the CDC track into the
1412 // FDC region.
1413 bool DTrackCandidate_factory::MatchMethod3(const DTrackCandidate *cdccan,
1414 vector<int> &forward_matches
1415 ){
1416 // Get hits already linked to this candidate from associated objects
1417 vector<const DCDCTrackHit *>cdchits;
1418 cdccan->GetT(cdchits);
1419 stable_sort(cdchits.begin(), cdchits.end(), CDCHitSortByLayerincreasing);
1420
1421 // loop over fdc candidates
1422 for (unsigned int k=0;k<fdctrackcandidates.size();k++){
1423 if (forward_matches[k]==0){
1424 const DTrackCandidate *fdccan = fdctrackcandidates[k];
1425 // fdc and cdc candidate momenta
1426 double p_fdc=fdccan->momentum().Mag();
1427 double p_cdc=cdccan->momentum().Mag();
1428 if (p_fdc/p_cdc>0.5){
1429 // Get the segment data
1430 vector<const DFDCSegment *>segments;
1431 fdccan->GetT(segments);
1432 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
1433
1434 // Only try to match candidate if this fdc candidate has hits in the
1435 // first package
1436 if (segments[0]->package>0) continue;
1437
1438
1439 // Abort if the track would have to pass from one quadrant into the opposite
1440 // quadrant (this is more likely two roughly back-to-back tracks rather than
1441 // a single track).
1442 const DVector2 fdc_hit_pos=segments[0]->hits[0]->xy;
1443 const DVector3 cdc_wire_origin=cdchits[0]->wire->origin;
1444 if (cdc_wire_origin.x()*fdc_hit_pos.X()<0.
1445 && cdc_wire_origin.y()*fdc_hit_pos.Y()<0.){
1446 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1446<<" "
<< "Skipping match of potential back-to-back tracks." <<endl;
1447 continue;
1448 }
1449
1450 // Momentum and position vectors for the CDC candidate
1451 DVector3 mom=cdccan->momentum();
1452 DVector3 pos=cdccan->position();
1453 double q=cdccan->charge();
1454
1455 // Try to match unmatched fdc candidates
1456 int num_match=0;
1457 int num_hits=0;
1458 for (unsigned int m=0;m<segments.size();m++){
1459 for (unsigned int n=0;n<segments[m]->hits.size();n++){
1460 unsigned int ind=segments[m]->hits.size()-1-n;
1461 const DFDCPseudo *hit=segments[m]->hits[ind];
1462
1463 if (pos.Perp()<48.5){
1464 ProjectHelixToZ(hit->wire->origin.z(),q,mom,pos);
1465
1466 // difference
1467 DVector2 XY=hit->xy;
1468 double dx=XY.X()-pos.x();
1469 double dy=XY.Y()-pos.y();
1470 double dr2=dx*dx+dy*dy;
1471
1472 double variance=1.0;
1473 double prob = isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
1474 if (prob>0.01) num_match++;
1475
1476 num_hits++;
1477 }
1478 }
1479 if (num_match>=3
1480 || (num_match>0 && double(num_match)/double(num_hits)>0.33)){
1481 DTrackCandidate *can = new DTrackCandidate;
1482
1483 can->setPID(cdccan->PID());
1484 can->used_cdc_indexes=cdccan->used_cdc_indexes;
1485
1486 // mark the fdc track candidate as matched
1487 forward_matches[k]=1;
1488
1489 // Add cdc hits to the candidate
1490 for (unsigned int m=0;m<cdchits.size();m++){
1491 can->AddAssociatedObject(cdchits[m]);
1492 }
1493
1494 // Add fdc hits to the candidate
1495 for (unsigned int m=0;m<segments.size();m++){
1496 for (unsigned int n=0;n<segments[m]->hits.size();n++){
1497 can->AddAssociatedObject(segments[m]->hits[n]);
1498 }
1499 }
1500
1501 // average Bz
1502 double Bz_avg=0.;
1503
1504 // Redo helical fit with all available hits
1505 DHelicalFit fit;
1506 if (DoRefit(fit,segments,cdchits,Bz_avg)==NOERROR){
1507 // Determine the polar angle
1508 double theta=fdccan->momentum().Theta();
1509 double theta_cdc=cdccan->momentum().Theta();
1510 if (segments.size()==1 && theta_cdc<M_PI_40.78539816339744830962){
1511 double numcdc=double(cdchits.size());
1512 double numfdc=segments[0]->hits.size();
1513 theta=(theta*numfdc+theta_cdc*numcdc)/(numfdc+numcdc);
1514 }
1515 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
1516
1517 // Redo the line fit
1518 fit.FitLineRiemann();
1519
1520 // Set the charge
1521 fit.FindSenseOfRotation();
1522 Particle_t locPID = ((FactorForSenseOfRotation*fit.h > 0.0) ? PiPlus : PiMinus);
1523 can->setPID(locPID);
1524 // FDC hit
1525 const DFDCPseudo *fdchit=segments[0]->hits[0];
1526 double zhit=fdchit->wire->origin.z();
1527 pos.SetXYZ(fdchit->xy.X(),fdchit->xy.Y(),zhit);
1528 UpdatePositionAndMomentum(fit,Bz_avg,cdchits[0]->wire->origin,
1529 pos,mom);
1530
1531 // circle parameters
1532 can->rc=fit.r0;
1533 can->xc=fit.x0;
1534 can->yc=fit.y0;
1535
1536 can->chisq=fit.chisq;
1537 can->Ndof=fit.ndof;
1538 can->setMomentum(mom);
1539 can->setPosition(pos);
1540 }
1541 else{
1542 //_DBG_ << endl;
1543 // circle parameters
1544 can->rc=cdccan->rc;
1545 can->xc=cdccan->xc;
1546 can->yc=cdccan->yc;
1547 can->Ndof=cdccan->Ndof;
1548 can->chisq=cdccan->chisq;
1549 can->setMomentum(cdccan->momentum());
1550 can->setPosition(cdccan->position());
1551 }
1552
1553 trackcandidates.push_back(can);
1554
1555 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1555<<" "
<< ".. matched to FDC candidate #" << k <<endl;
1556
1557 return true;
1558 } // got a match
1559 } // loop over segments
1560 } // check that we have not already matched to this fdc candidate
1561 } // momentum check
1562 } // loop over fdc candidates
1563
1564 return false;
1565 }
1566
1567// This method tries to match unmatched fdc candidates
1568bool DTrackCandidate_factory::MatchMethod4(const DTrackCandidate *srccan,
1569 vector<int> &forward_matches,
1570 int &num_fdc_cands_remaining){
1571 // Get segments already linked to this candidate from associated objects
1572 vector<const DFDCSegment *>src_segments;
1573 srccan->GetT(src_segments);
1574
1575 if (src_segments.size()==1) return false;
1576 stable_sort(src_segments.begin(), src_segments.end(), SegmentSortByLayerincreasing);
1577
1578 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1578<<" "
<< "Attempting matching method #4..." <<endl;
1579
1580 unsigned int pack1_last=src_segments[src_segments.size()-1]->package;
1581 unsigned int pack1_first=src_segments[0]->package;
1582
1583 for (unsigned int k=0;k<fdctrackcandidates.size();k++){
1584 if (num_fdc_cands_remaining==0) break;
1585 if (forward_matches[k]==0){
1586 const DTrackCandidate *fdccan = fdctrackcandidates[k];
1587
1588 // Get the segment data
1589 vector<const DFDCSegment *>segments;
1590 fdccan->GetT(segments);
1591 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
1592
1593 const DFDCPseudo *firsthit=segments[0]->hits[0];
1594 unsigned int pack2_first=segments[0]->package;
1595 unsigned int pack2_last=segments[segments.size()-1]->package;
1596
1597 // if (pack2_first>pack1_last || pack2_last<pack1_first){
1598 if (pack2_first-pack1_last==1 || pack1_first-pack2_last==1){
1599 // Momentum and position vectors for the input candidate
1600 DVector3 mom=srccan->momentum();
1601 DVector3 pos=srccan->position();
1602 double q=srccan->charge();
1603 DVector3 norm(0.,0.,1.);
1604
1605 if (pack2_last<pack1_first){
1606 mom=(-1.0)*mom;
1607 }
1608
1609 // Swim to the first hit in the candidate to which we wish to match
1610 // using the stepper
1611 stepper->SetCharge(q);
1612 stepper->SwimToPlane(pos,mom,firsthit->wire->origin,norm,NULL__null);
1613
1614 double dx=pos.x()-firsthit->xy.X();
1615 double dy=pos.y()-firsthit->xy.Y();
1616 double d2=dx*dx+dy*dy;
1617 double variance=1.;
1618 double prob=TMath::Prob(d2/variance,1);
1619
1620 unsigned int num_match=(prob>0.01)?1:0;
1621
1622 // Try to match unmatched fdc candidates
1623 for (unsigned int i=1;i<segments[0]->hits.size();i++){
1624 const DFDCPseudo *hit=segments[0]->hits[i];
1625
1626 if (pos.Perp()<48.5){
1627 ProjectHelixToZ(hit->wire->origin.z(),q,mom,pos);
1628
1629 DVector2 XY=hit->xy;
1630 double dx=XY.X()-pos.x();
1631 double dy=XY.Y()-pos.y();
1632 double dr2=dx*dx+dy*dy;
1633
1634 double variance=1.0;
1635 double prob = isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
1636 if (prob>0.01) num_match++;
1637 }
1638 }
1639 if (num_match>=3){
1640 forward_matches[k]=1;
1641
1642 // Create new candidate for output
1643 DTrackCandidate *can = new DTrackCandidate;
1644
1645 // average Bz
1646 double Bz_avg=0.;
1647 unsigned int num_hits=0;
1648
1649 // Create a new DHelicalFit object for fitting combined data
1650 DHelicalFit fit;
1651 // Fake point at origin
1652 fit.AddHitXYZ(0.,0.,TARGET_Z,BEAM_VAR1.,BEAM_VAR1.,0.,true);
1653 // Add hits to the fit object and also to the track candidate
1654 // itself as associated objects
1655 for (unsigned int m=0;m<src_segments.size();m++){
1656 for (unsigned int n=0;n<src_segments[m]->hits.size();n++){
1657 const DFDCPseudo *fdchit=src_segments[m]->hits[n];
1658 fit.AddHit(fdchit);
1659 can->AddAssociatedObject(fdchit);
1660
1661 //bfield->GetField(x,y,z,Bx,By,Bz);
1662 //Bz_avg-=Bz;
1663 Bz_avg+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),
1664 fdchit->wire->origin.z());
1665 }
1666 num_hits+=src_segments[m]->hits.size();
1667 }
1668 for (unsigned int m=0;m<segments.size();m++){
1669 for (unsigned int n=0;n<segments[m]->hits.size();n++){
1670 const DFDCPseudo *fdchit=segments[m]->hits[n];
1671 fit.AddHit(fdchit);
1672 can->AddAssociatedObject(fdchit);
1673
1674 //bfield->GetField(x,y,z,Bx,By,Bz);
1675 //Bz_avg-=Bz;
1676 Bz_avg+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),
1677 fdchit->wire->origin.z());
1678 }
1679 num_hits+=segments[m]->hits.size();
1680 }
1681
1682 // Fit the points to a circle
1683 if (fit.FitCircleRiemann(segments[0]->rc)==NOERROR){
1684 // Compute new transverse momentum
1685 Bz_avg=fabs(Bz_avg)/double(num_hits);
1686
1687 // Guess for theta and z from input candidates
1688 double theta=fdccan->momentum().Theta();
1689 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
1690 fit.z_vertex=srccan->position().Z();
1691
1692 // Redo line fit
1693 fit.FitLineRiemann();
1694
1695 double p=0.003*fit.r0*Bz_avg/cos(atan(fit.tanl));
1696 if (p>10.){ // Check for extremely stiff tracks, some of which
1697 // will have unphysical momenta... try alternate circle fit
1698 fit.FitCircle();
1699 }
1700 // Guess charge from fit
1701 fit.h=GetSenseOfRotation(fit,firsthit,srccan->position());
1702 Particle_t locPID = ((FactorForSenseOfRotation*fit.h > 0.0) ? PiPlus : PiMinus);
1703 can->setPID(locPID);
1704
1705 // put z position just upstream of the first hit in z
1706 const DHFHit_t *myhit=fit.GetHits()[0];
1707 pos.SetXYZ(myhit->x,myhit->y,myhit->z);
1708 GetPositionAndMomentum(myhit->z-1.,fit,Bz_avg,pos,mom);
1709
1710 // circle parameters
1711 can->rc=fit.r0;
1712 can->xc=fit.x0;
1713 can->yc=fit.y0;
1714
1715 can->setPosition(pos);
1716 can->setMomentum(mom);
1717 can->chisq=fit.chisq;
1718 can->Ndof=fit.ndof;
1719 trackcandidates.push_back(can);
1720
1721 num_fdc_cands_remaining--;
1722
1723 if (DEBUG_LEVEL>0)
1724 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1724<<" "
<< "Found a match using method #4" <<endl;
1725 return true;
1726 } // circle fit
1727 } // got a match?
1728 } // is the first package in the new fdc candidate downstream of the last?
1729 } // check that we have not already matched this fdc candidate
1730 } // loop over fdc track candidates
1731
1732 return false;
1733}
1734
1735// Matching method to try to deal with CDC candidates that do not point
1736// directly at the the cdc endplate but could possibly be matched to FDC
1737// candidates.
1738bool DTrackCandidate_factory::MatchMethod5(DTrackCandidate *can,
1739 vector<const DCDCTrackHit *>&cdchits,
1740 vector<int> &forward_matches
1741 ){
1742 // Loop over the fdc track candidates
1743 for (unsigned int k=0;k<fdctrackcandidates.size();k++){
1744 if (forward_matches[k]==0){
1745 const DTrackCandidate *fdccan = fdctrackcandidates[k];
1746
1747 unsigned int num_match=0;
1748 unsigned int num_cdc=0;
1749
1750 DVector3 pos=fdccan->position();
1751 DVector3 mom=fdccan->momentum();
1752 double q=fdccan->charge();
1753
1754 for (unsigned int m=0;m<cdchits.size();m++){
1755 double variance=1.0;
1756 // Use a helical approximation to the track to match both axial and
1757 // stereo wires
1758 double dr2=DocaToHelix(cdchits[m],q,pos,mom);
1759 double prob=isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
1760
1761 if (prob>0.01) num_match++;
1762 if (DEBUG_LEVEL>1) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1762<<" "
<< "CDC s: " << cdchits[m]->wire->straw
1763 << " r: " << cdchits[m]->wire->ring
1764 << " prob: " << prob << endl;
1765
1766 num_cdc++;
1767 }
1768
1769 if (num_match>=3 && double(num_match)/double(num_cdc)>0.33){
1770 // Get the segment data
1771 vector<const DFDCSegment *>segments;
1772 fdccan->GetT(segments);
1773
1774 // JANA does not maintain the order that the segments were added
1775 // as associated objects. Therefore, we need to reorder them here
1776 // so segment[0] is the most upstream segment.
1777 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
1778
1779 // Abort if the track would have to pass from one quadrant into the opposite
1780 // quadrant (this is more likely two roughly back-to-back tracks rather than
1781 // a single track).
1782 const DVector2 fdc_hit_pos=segments[0]->hits[0]->xy;
1783 const DVector3 cdc_wire_origin=cdchits[0]->wire->origin;
1784 if (cdc_wire_origin.x()*fdc_hit_pos.X()<0.
1785 && cdc_wire_origin.y()*fdc_hit_pos.Y()<0.){
1786 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1786<<" "
<< "Skipping match of potential back-to-back tracks." <<endl;
1787 continue;
1788 }
1789
1790 // Mark this fdc candidate as having a match to a cdc candidate
1791 forward_matches[k]=1;
1792
1793 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1793<<" "
<< "... matched to FDC candidate #" << k <<endl;
1794
1795 // Add fdc hits to the candidate
1796 for (unsigned int m=0;m<segments.size();m++){
1797 for (unsigned int n=0;n<segments[m]->hits.size();n++){
1798 can->AddAssociatedObject(segments[m]->hits[n]);
1799 }
1800 }
1801
1802 // Average Bz
1803 double Bz_avg=0.;
1804
1805 // Instantiate the helical fitter to do the refit
1806 DHelicalFit fit;
1807 if (DoRefit(fit,segments,cdchits,Bz_avg)==NOERROR){
1808 // circle parameters
1809 can->rc=fit.r0;
1810 can->xc=fit.x0;
1811 can->yc=fit.y0;
1812
1813 // Determine the polar angle
1814 double theta=fdccan->momentum().Theta();
1815 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
1816
1817 Particle_t locPID = ((FactorForSenseOfRotation*fit.h > 0.0) ? PiPlus : PiMinus);
1818 can->setPID(locPID);
1819
1820 // FDC hit
1821 const DFDCPseudo *fdchit=segments[0]->hits[0];
1822 double zhit=fdchit->wire->origin.z();
1823 pos.SetXYZ(fdchit->xy.X(),fdchit->xy.Y(),zhit);
1824 UpdatePositionAndMomentum(fit,Bz_avg,cdchits[0]->wire->origin,
1825 pos,mom);
1826
1827 can->chisq=fit.chisq;
1828 can->Ndof=fit.ndof;
1829 can->setMomentum(mom);
1830 can->setPosition(pos);
1831 }
1832 return true;
1833 } // check for match
1834 } // check that the candidate has not already been matched
1835 } // loop over fdc candidates
1836
1837 return false;
1838}
1839
1840// Method to match FDC candidates with stray CDC hits unassociated with track
1841// candidates
1842void DTrackCandidate_factory::MatchMethod6(DTrackCandidate *can,
1843 vector<const DFDCPseudo*>&fdchits,
1844 vector<unsigned int>&used_cdc_hits,
1845 unsigned int &num_unmatched_cdcs
1846 ){
1847 // Input candidate parameters
1848 DVector3 pos=can->position();
1849 DVector3 mom=can->momentum();
1850 double q=can->charge();
1851
1852 // Variables to keep track of cdc hits
1853 bool got_inner_index=false;
1854 unsigned int inner_index=0;
1855 int id_for_smallest_dr=-1;
1856 int old_ring=-1;
1857 double dr2_min=1e6;
1858
1859 for (unsigned int k=0;k<used_cdc_hits.size();k++){
1860 // We only want to use one hit from a given ring to avoid confusing the
1861 // circle refit with curlers...
1862 if (mycdchits[k]->wire->ring!=old_ring){
1863 if (id_for_smallest_dr>=0){
1864 if (!used_cdc_hits[id_for_smallest_dr]){
1865 num_unmatched_cdcs--;
1866 used_cdc_hits[id_for_smallest_dr]=1;
1867
1868 can->used_cdc_indexes.push_back(id_for_smallest_dr);
1869 can->AddAssociatedObject(mycdchits[id_for_smallest_dr]);
1870
1871 if (got_inner_index==false){
1872 inner_index=id_for_smallest_dr;
1873 got_inner_index=true;
1874 }
1875 }
1876 }
1877 // Reset matching variables
1878 dr2_min=1e6;
1879 id_for_smallest_dr=-1;
1880 }
1881
1882 if (!used_cdc_hits[k]){
1883 double variance=1.0;
1884 // Use a helical approximation to the track to match both axial and
1885 // stereo wires
1886 double dr2=DocaToHelix(mycdchits[k],q,pos,mom);
1887 double prob=isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
1888
1889 if (prob>0.5){
1890 // Look for closest match
1891 if (dr2<dr2_min){
1892 dr2_min=dr2;
1893 id_for_smallest_dr=k;
1894 }
1895 }
1896 }
1897 old_ring=mycdchits[k]->wire->ring;
1898 }
1899 // Grab the last potential match
1900 if (id_for_smallest_dr>=0){
1901 if (!used_cdc_hits[id_for_smallest_dr]){
1902 num_unmatched_cdcs--;
1903 used_cdc_hits[id_for_smallest_dr]=1;
1904
1905 can->used_cdc_indexes.push_back(id_for_smallest_dr);
1906 can->AddAssociatedObject(mycdchits[id_for_smallest_dr]);
1907 }
1908 }
1909
1910 // We found some matched hits. Update the start position of the candidate.
1911 if (got_inner_index){
1912 const DFDCPseudo *firsthit=fdchits[0];
1913
1914 // Compute the average Bz
1915 double Bz_avg=0.,denom=0.;
1916 for (unsigned int m=0;m<fdchits.size();m++){
1917 const DFDCPseudo *fdchit=fdchits[m];
1918 double x=fdchit->xy.X();
1919 double y=fdchit->xy.Y();
1920 double z=fdchit->wire->origin.z();
1921
1922 Bz_avg+=bfield->GetBz(x,y,z);
1923 denom+=1.;
1924 }
1925 Bz_avg=fabs(Bz_avg)/denom;
1926
1927 // Store the current track parameters in the DHelicalFit class
1928 DHelicalFit fit;
1929 fit.r0=mom.Perp()/(0.003*Bz_avg);
1930 fit.phi=mom.Phi();
1931 fit.h=q*FactorForSenseOfRotation;
1932 fit.x0=pos.x()-fit.h*fit.r0*sin(fit.phi);
1933 fit.y0=pos.y()+fit.h*fit.r0*cos(fit.phi);
1934 fit.tanl=tan(M_PI_21.57079632679489661923-mom.Theta());
1935 fit.z_vertex=0; // actualy we don't need this..
1936 // Use fdc hit for input to the following routines because the z-position is
1937 // well-defined...
1938 double zhit=firsthit->wire->origin.z();
1939 pos.SetXYZ(firsthit->xy.X(),firsthit->xy.Y(),zhit);
1940 UpdatePositionAndMomentum(fit,Bz_avg,mycdchits[inner_index]->wire->origin,
1941 pos,mom);
1942
1943 // update the track parameters
1944 can->setMomentum(mom);
1945 can->setPosition(pos);
1946
1947 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1947<<" "
<< "... matched stray CDC hits ..." << endl;
1948 } // match at least one cdc hit
1949}
1950
1951// This method tries to match unmatched fdc candidates to candidates that
1952// already have fdc/cdc matches
1953bool DTrackCandidate_factory::MatchMethod7(DTrackCandidate *srccan,
1954 vector<int> &forward_matches,
1955 int &num_fdc_cands_remaining){
1956 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<1956<<" "
<< "Attempting matching method #7..." <<endl;
1957
1958 // Get the hits associated with this candidate
1959 vector<const DFDCPseudo *>fdchits;
1960 srccan->GetT(fdchits);
1961 if (fdchits.size()==0) return false;
1962
1963 stable_sort(fdchits.begin(),fdchits.end(),FDCHitSortByLayerincreasing);
1964 unsigned int pack1_last=(fdchits[fdchits.size()-1]->wire->layer-1)/6;
1965
1966 for (unsigned int k=0;k<fdctrackcandidates.size();k++){
1967 if (num_fdc_cands_remaining==0) break;
1968 if (forward_matches[k]==0){
1969 const DTrackCandidate *fdccan = fdctrackcandidates[k];
1970
1971 // Get the segment data
1972 vector<const DFDCSegment *>segments;
1973 fdccan->GetT(segments);
1974 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
1975
1976 const DFDCPseudo *firsthit=segments[0]->hits[0];
1977 unsigned int pack2_first=segments[0]->package;
1978
1979 if (pack2_first-pack1_last==1){ // match in adjacent packages
1980 // Momentum and position vectors for the input candidate
1981 DVector3 mom=srccan->momentum();
1982 DVector3 pos=srccan->position();
1983 double q=srccan->charge();
1984 DVector3 norm(0.,0.,1.);
1985
1986 // Swim to the first hit in the candidate to which we wish to match
1987 // using the stepper
1988 stepper->SetCharge(q);
1989 stepper->SwimToPlane(pos,mom,firsthit->wire->origin,norm,NULL__null);
1990
1991 double dx=pos.x()-firsthit->xy.X();
1992 double dy=pos.y()-firsthit->xy.Y();
1993 double d2=dx*dx+dy*dy;
1994 double variance=1.;
1995 double prob=TMath::Prob(d2/variance,1);
1996
1997 unsigned int num_match=(prob>0.01)?1:0;
1998
1999 // Try to match unmatched fdc candidates
2000 for (unsigned int i=1;i<segments[0]->hits.size();i++){
2001 const DFDCPseudo *hit=segments[0]->hits[i];
2002
2003 if (pos.Perp()<48.5){
2004 ProjectHelixToZ(hit->wire->origin.z(),q,mom,pos);
2005
2006 DVector2 XY=hit->xy;
2007 double dx=XY.X()-pos.x();
2008 double dy=XY.Y()-pos.y();
2009 double dr2=dx*dx+dy*dy;
2010
2011 double variance=1.0;
2012 double prob = isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
2013 if (prob>0.01) num_match++;
2014 }
2015 }
2016 if (num_match>=3){
2017 forward_matches[k]=1;
2018 num_fdc_cands_remaining--;
2019
2020 // average Bz
2021 double Bz=0.;
2022 unsigned int num_hits=0;
2023
2024 // Create a new DHelicalFit object for fitting combined data
2025 DHelicalFit fit;
2026
2027 // Get the cdc hits associated with this track candidate and add the
2028 // axial straws to the list of hits to use in the circle fit
2029 vector<const DCDCTrackHit *>cdchits;
2030 srccan->GetT(cdchits);
2031 stable_sort(cdchits.begin(), cdchits.end(), CDCHitSortByLayerincreasing);
2032 for (unsigned int i=0;i<cdchits.size();i++){
2033 if (cdchits[i]->is_stereo==false){
2034 double cov=0.213; //guess
2035 const DVector3 origin=cdchits[i]->wire->origin;
2036 double x=origin.x(),y=origin.y(),z=origin.z();
2037 fit.AddHitXYZ(x,y,z,cov,cov,0.,true);
2038 Bz+=bfield->GetBz(x,y,z);
2039 num_hits++;
2040 }
2041 }
2042 // Add the FDC hits from the existing track to this list
2043 for (unsigned int i=0;i<fdchits.size();i++){
2044 fit.AddHit(fdchits[i]);
2045 double zhit=fdchits[i]->wire->origin.z();
2046
2047 Bz+=bfield->GetBz(fdchits[i]->xy.X(),fdchits[i]->xy.Y(),zhit);
2048 num_hits++;
2049
2050 if (zhit<firsthit->wire->origin.z()){
2051 firsthit=fdchits[i];
2052 }
2053 }
2054 // Add the new set of FDC hits; also add them as associated objects
2055 // to the track
2056 for (unsigned int m=0;m<segments.size();m++){
2057 for (unsigned int n=0;n<segments[m]->hits.size();n++){
2058 const DFDCPseudo *fdchit=segments[m]->hits[n];
2059 fit.AddHit(fdchit);
2060 double zhit=fdchit->wire->origin.z();
2061
2062 Bz+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),zhit);
2063 srccan->AddAssociatedObject(fdchit);
2064 }
2065 num_hits+=segments[m]->hits.size();
2066 }
2067 Bz=fabs(Bz)/double(num_hits);
2068
2069 // Redo the circle fit with the extra hits
2070 if (fit.FitCircleRiemann(srccan->rc)==NOERROR){
2071 // Determine the polar angle
2072 double theta=srccan->momentum().Theta();
2073 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
2074
2075 double p=0.003*fit.r0*Bz/cos(atan(fit.tanl));
2076 if ((cdchits.size())>0?(p>3.):(p>10.)){
2077 // Suspiciously high momentum: try alternate circle fit...
2078 fit.FitCircle();
2079 }
2080
2081 if (cdchits.size()>0){
2082 // FDC hit
2083 double zhit=firsthit->wire->origin.z();
2084 pos.SetXYZ(firsthit->xy.X(),firsthit->xy.Y(),zhit);
2085 UpdatePositionAndMomentum(fit,Bz,cdchits[0]->wire->origin,
2086 pos,mom);
2087 }
2088 else{
2089 // put z position just upstream of the first hit in z
2090 const DHFHit_t *myhit=fit.GetHits()[0];
2091 pos.SetXYZ(myhit->x,myhit->y,myhit->z);
2092 GetPositionAndMomentum(myhit->z-1.,fit,Bz,pos,mom);
2093 }
2094 srccan->rc=fit.r0;
2095 srccan->xc=fit.x0;
2096 srccan->yc=fit.y0;
2097
2098 srccan->chisq=fit.chisq;
2099 srccan->Ndof=fit.ndof;
2100 srccan->setMomentum(mom);
2101 srccan->setPosition(pos);
2102 }
2103
2104 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2104<<" "
<< "Found a match using method #7" <<endl;
2105 return true;
2106 } // got a match?
2107 } // is the first package in the new fdc candidate downstream of the last?
2108 } // check that we have not already matched this fdc candidate
2109 } // loop over fdc track candidates
2110
2111 return false;
2112}
2113
2114
2115// This method tries to improve the quality of the circle fit of a cdc
2116// candidate by assuming that if the outermost hit is in a stereo straw,
2117// if this track is going to match to an fdc candidate, the location of the
2118// hit along the straw is likely to be near the end of the straw, thus
2119// providing another useful point on the circle. After refitting the circle,
2120// the code adjusts the dip angle and tries to match to the remaining fdc
2121// candidates.
2122bool DTrackCandidate_factory::MatchMethod8(const DTrackCandidate *cdccan,
2123 vector<int> &forward_matches
2124 ){
2125 // Get the cdc hits associated with this track candidate
2126 vector<const DCDCTrackHit *>cdchits;
2127 cdccan->GetT(cdchits);
2128 stable_sort(cdchits.begin(), cdchits.end(), CDCHitSortByLayerincreasing);
2129
2130 unsigned int last_index=cdchits.size()-1;
2131 if (cdchits[last_index]->is_stereo==true
2132 && cdchits[last_index]->wire->ring<13){
2133 DHelicalFit fit;
2134
2135 // Assume the outermost stereo hit occurs near the end of the straw
2136 DVector3 origin=cdchits[last_index]->wire->origin;
2137 DVector3 dir=cdchits[last_index]->wire->udir;
2138 DVector3 wirepos=origin+(75./dir.z())*dir;
2139 double cov=0.2;
2140 double x=wirepos.x(),y=wirepos.y(),z=wirepos.z();
2141 fit.AddHitXYZ(x,y,z,cov,cov,0,true);
2142 double Bz=bfield->GetBz(x,y,z);
2143 int num_hits=1;
2144
2145 // Add the cdc axial wires to the list of hits to use in the fit
2146 for (unsigned int k=0;k<cdchits.size();k++){
2147 if (cdchits[k]->is_stereo==false){
2148 cov=0.2; //guess
2149 origin=cdchits[k]->wire->origin;
2150 double x=origin.x(),y=origin.y(),z=origin.z();
2151 fit.AddHitXYZ(x,y,z,cov,cov,0.,true);
2152 Bz+=bfield->GetBz(x,y,z);
2153 num_hits++;
2154 }
2155 }
2156 Bz=fabs(Bz)/num_hits;
2157
2158 // Fit the points to a circle assuming that the circle goes through the
2159 // origin.
2160 if (fit.FitCircle()!=NOERROR) return false;
2161
2162 // Determine the tangent of the dip angle
2163 double tworc=2.*fit.r0;
2164 double ratio=wirepos.Perp()/tworc;
2165 double sperp=tworc*((ratio<1.)?asin(ratio):M_PI_21.57079632679489661923);
2166 fit.tanl=(wirepos.z()-TARGET_Z)/sperp;
2167
2168 // Find sense of rotation (proportional to the charge)
2169 fit.GuessChargeFromCircleFit();
2170 double q=fit.h*FactorForSenseOfRotation;
2171
2172 // Provide an initial guess for the position and momentum that is just
2173 // outside the CDC tracking volume
2174 DVector3 pos=wirepos,mom;
2175 UpdatePositionAndMomentum(fit,Bz,cdchits[0]->wire->origin,pos,mom);
2176
2177 // Set the charge for the stepper
2178 stepper->SetCharge(q);
2179 // Vector normal to the fdc planes
2180 DVector3 norm(0.,0.,1.);
2181
2182 // Loop over the fdc candidates looking for a match
2183 for (unsigned int k=0;k<fdctrackcandidates.size();k++){
2184 if (forward_matches[k]==0){
2185 const DTrackCandidate *fdccan = fdctrackcandidates[k];
2186
2187 // Get the segment data
2188 vector<const DFDCSegment *>segments;
2189 fdccan->GetT(segments);
2190 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
2191
2192 // only do this for candidates with segments in the first package
2193 if (segments[0]->package>0) continue;
2194
2195 const DFDCPseudo *firsthit=segments[0]->hits[0];
2196
2197 // Make copies of the momentum and position vectors for input to
2198 // the swimmer
2199 DVector3 my_mom(mom);
2200 DVector3 my_pos(pos);
2201
2202 // Swim to the first hit in the candidate to which we wish to match
2203 // using the stepper
2204 stepper->SwimToPlane(my_pos,my_mom,firsthit->wire->origin,norm,NULL__null);
2205
2206 // Match based on proximity of projection to hit
2207 double dx=my_pos.x()-firsthit->xy.X();
2208 double dy=my_pos.y()-firsthit->xy.Y();
2209 double d2=dx*dx+dy*dy;
2210 double variance=1.;
2211 double prob=TMath::Prob(d2/variance,1);
2212
2213 unsigned int num_match=(prob>0.01)?1:0;
2214
2215 // Try to match further hits in most upstream segment
2216 for (unsigned int i=1;i<segments[0]->hits.size();i++){
2217 const DFDCPseudo *hit=segments[0]->hits[i];
2218
2219 if (my_pos.Perp()<48.5){
2220 ProjectHelixToZ(hit->wire->origin.z(),q,my_mom,my_pos);
2221
2222 DVector2 XY=hit->xy;
2223 double dx=XY.X()-my_pos.x();
2224 double dy=XY.Y()-my_pos.y();
2225 double dr2=dx*dx+dy*dy;
2226
2227 double variance=1.0;
2228 double prob = isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
2229 if (prob>0.01) num_match++;
2230 }
2231 }
2232 if (num_match>=3){
2233 forward_matches[k]=1;
2234
2235 // Keep track of magnetic field in FDC
2236 double Bz_fdc=0;
2237 unsigned int num_hits_fdc=0;
2238
2239 // Drop the first cdc hit in the list, since it isn't an
2240 // axial straw so the actual x,y position of the wire
2241 // depends on z, which we don't really know yet.
2242 fit.PruneHit(0);
2243
2244 // Add the fdc hits to the fit class
2245 for (unsigned int m=0;m<segments.size();m++){
2246 for (unsigned int n=0;n<segments[m]->hits.size();n++){
2247 const DFDCPseudo *fdchit=segments[m]->hits[n];
2248 fit.AddHit(fdchit);
2249
2250 Bz_fdc+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),
2251 fdchit->wire->origin.z());
2252 }
2253 num_hits_fdc+=segments[m]->hits.size();
2254 }
2255
2256 // Fake point at origin
2257 fit.AddHitXYZ(0.,0.,TARGET_Z,BEAM_VAR1.,BEAM_VAR1.,0.,true);
2258 // Fit the points to a circle
2259 if (fit.FitCircleRiemann(segments[0]->rc)==NOERROR){
2260 // Use the fdc track candidate to get tanl
2261 double theta=fdccan->momentum().Theta();
2262 double theta_cdc=cdccan->momentum().Theta();
2263 if (segments.size()==1 && theta_cdc<M_PI_40.78539816339744830962){
2264 double numcdc=double(cdchits.size());
2265 double numfdc=segments[0]->hits.size();
2266 theta=(theta*numfdc+theta_cdc*numcdc)/(numfdc+numcdc);
2267 }
2268 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
2269
2270 Bz=0.5*(Bz+fabs(Bz_fdc)/num_hits_fdc);
2271
2272 double p=0.003*fit.r0*Bz/cos(atan(fit.tanl));
2273 if (p>10.){
2274 // momentum is suspiciously high for a track going through both
2275 // the FDC and the CDC... try alternate circle fit
2276 fit.FitCircle();
2277 }
2278 // FDC hit
2279 const DFDCPseudo *fdchit=segments[0]->hits[0];
2280 double zhit=fdchit->wire->origin.z();
2281 pos.SetXYZ(fdchit->xy.X(),fdchit->xy.Y(),zhit);
2282 UpdatePositionAndMomentum(fit,Bz,cdchits[0]->wire->origin,pos,mom);
2283
2284 DTrackCandidate *can = new DTrackCandidate;
2285 // circle parameters
2286 can->rc=fit.r0;
2287 can->xc=fit.x0;
2288 can->yc=fit.y0;
2289
2290 can->setPID((q > 0.0) ? PiPlus : PiMinus);
2291 can->setMomentum(my_mom);
2292 can->setPosition(my_pos);
2293 can->chisq=fit.chisq;
2294 can->Ndof=fit.ndof;
2295
2296 // Add hits as associated objects
2297 for (unsigned int m=0;m<segments.size();m++){
2298 for (unsigned int n=0;n<segments[m]->hits.size();n++){
2299 const DFDCPseudo *fdchit=segments[m]->hits[n];
2300 can->AddAssociatedObject(fdchit);
2301 }
2302 }
2303 for (unsigned int n=0;n<cdchits.size();n++){
2304 can->AddAssociatedObject(cdchits[n]);
2305 }
2306
2307 trackcandidates.push_back(can);
2308
2309 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2309<<" "
<< "Matched using Method #8" <<endl;
2310
2311 return true;
2312 } // circle fit
2313 } // match criterion
2314 } // check that fdc candidate has not already been matched
2315 } // loop over fdc candidates
2316 } // Check that the outermost hit is a stereo hit
2317
2318 return false;
2319}
2320
2321
2322// Method to try to match unmatched FDC segments by forcing the circle fits
2323// to go through the origin.
2324bool DTrackCandidate_factory::MatchMethod9(unsigned int src_index,
2325 const DTrackCandidate *srccan,
2326 const DFDCSegment *segment,
2327 vector<const DTrackCandidate*>&cands,
2328 vector<int> &forward_matches){
2329 if (DEBUG_LEVEL>0){
2330 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2330<<" "
<< "Attempting Match method #9..." << endl;
2331 }
2332 double q=srccan->charge();
2333 int pack1=segment->package;
2334
2335 // Get hits from segment and redo fit forcing the circle to go through (0,0)
2336 DHelicalFit fit1;
2337 for (unsigned int n=0;n<segment->hits.size();n++){
2338 const DFDCPseudo *hit=segment->hits[n];
2339 fit1.AddHit(hit);
2340 }
2341 if (fit1.FitCircle()!=NOERROR) return false;
2342
2343 // Sense of rotation
2344 fit1.h=q*FactorForSenseOfRotation;
2345
2346 // Use the fdc track candidate to get tanl
2347 double theta=srccan->momentum().Theta();
2348 fit1.tanl=tan(M_PI_21.57079632679489661923-theta);
2349
2350 // Find the magnetic field at the first hit in the first segment
2351 double x=segment->hits[0]->xy.X();
2352 double y=segment->hits[0]->xy.Y();
2353 double z=segment->hits[0]->wire->origin.z();
2354 double Bz=fabs(bfield->GetBz(x,y,z));
2355
2356 // Get position and momentum for the first segment
2357 DVector3 mypos,mymom;
2358 GetPositionAndMomentum(z,fit1,Bz,mypos,mymom);
2359
2360 // Loop over the rest of the fdc track candidates, skipping those that have
2361 // already been used
2362 for (unsigned int k=src_index+1;k<forward_matches.size();k++){
2363 if (forward_matches[k]==0){
2364 const DTrackCandidate *can2=cands[k];
2365 // Get the segment data
2366 vector<const DFDCSegment *>segments2;
2367 can2->GetT(segments2);
2368
2369 int pack2=segments2[0]->package;
2370 if (abs(pack1-pack2)>0){
2371 // Get hits from the second segment and redo fit forcing circle
2372 // to go through (0,0)
2373 DHelicalFit fit2;
2374 for (unsigned int n=0;n<segments2[0]->hits.size();n++){
2375 const DFDCPseudo *hit=segments2[0]->hits[n];
2376 fit2.AddHit(hit);
2377 }
2378 if (fit2.FitCircle()!=NOERROR) continue;
2379
2380 // Match using centers of circles
2381 double dx=fit1.x0-fit2.x0;
2382 double dy=fit1.y0-fit2.y0;
2383 double circle_center_diff2=dx*dx+dy*dy;
2384 double got_match=false;
2385 if (circle_center_diff2<9.0) got_match=true;
2386 // try another matching method here if got_match==false
2387 else{
2388 // Sense of rotation
2389 double q2=can2->charge();
2390 fit2.h=q2*FactorForSenseOfRotation;
2391
2392 // Use the fdc track candidate to get tanl
2393 theta=can2->momentum().Theta();
2394 fit2.tanl=tan(M_PI_21.57079632679489661923-theta);
2395
2396 // Try to match segments by swimming through the field
2397 got_match=MatchMethod11(q,mypos,mymom,fit2,segment,segments2[0]);
2398 // _DBG_ << endl;
2399 }
2400 if (got_match){
2401 forward_matches[k]=1;
2402 forward_matches[src_index]=1;
2403
2404 // Create a new DTrackCandidate for output
2405 DTrackCandidate *can = new DTrackCandidate;
2406
2407 // variables for finding <Bz>
2408 double Bz=0;
2409 int num_hits=0;
2410
2411 // Add hits from first segment as associated objects
2412 for (unsigned int n=0;n<segment->hits.size();n++){
2413 const DFDCPseudo *fdchit=segment->hits[n];
2414 can->AddAssociatedObject(fdchit);
2415
2416 Bz+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),
2417 fdchit->wire->origin.z());
2418 num_hits++;
2419 }
2420
2421 // Add the hits from the second segment to the first fit object
2422 // and refit the circle. Also add them as associated objects
2423 // to the new candidate.
2424 for (unsigned int n=0;n<segments2[0]->hits.size();n++){
2425 const DFDCPseudo *hit=segments2[0]->hits[n];
2426 fit1.AddHit(hit);
2427 can->AddAssociatedObject(hit);
2428
2429 Bz+=bfield->GetBz(hit->xy.X(),hit->xy.Y(),
2430 hit->wire->origin.z());
2431 num_hits++;
2432 }
2433 Bz=fabs(Bz)/double(num_hits);
2434
2435 // Initialize variables needed for output
2436 DVector3 mom=srccan->momentum();
2437 DVector3 pos=srccan->position();
2438
2439 can->Ndof=srccan->Ndof;
2440 can->chisq=srccan->chisq;
2441
2442 if (fit1.FitCircleRiemann(fit1.r0)==NOERROR){
2443 can->Ndof=fit1.ndof;
2444 can->chisq=fit1.chisq;
2445
2446 // Redo line fit
2447 fit1.FitLineRiemann();
2448
2449 double p=0.003*fit1.r0*Bz/cos(atan(fit1.tanl));
2450 if (p>10.){
2451 // Try an alternate circle fit
2452 fit1.FitCircle();
2453 }
2454
2455 // Guess charge from fit
2456 fit1.h=GetSenseOfRotation(fit1,segments2[0]->hits[0],
2457 srccan->position());
2458 q=FactorForSenseOfRotation*fit1.h;
2459
2460 // put z position just upstream of the first hit in z
2461 const DHFHit_t *myhit=fit1.GetHits()[0];
2462 pos.SetXYZ(myhit->x,myhit->y,myhit->z);
2463 GetPositionAndMomentum(myhit->z-1.,fit1,Bz,pos,mom);
2464 }
2465 // circle parameters
2466 can->rc=fit1.r0;
2467 can->xc=fit1.x0;
2468 can->yc=fit1.y0;
2469
2470 can->setPID((q > 0.0) ? PiPlus : PiMinus);
2471 can->setPosition(pos);
2472 can->setMomentum(mom);
2473
2474 trackcandidates.push_back(can);
2475
2476 if (DEBUG_LEVEL>0){
2477 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2477<<" "
<< "Match method #9 succeeded..." << endl;
2478 }
2479
2480 return true;
2481 } // circle center match
2482 } // different packages?
2483 } // already matched?
2484 } // loop over tracks
2485
2486 return false;
2487}
2488
2489// Method to try to match unmatched FDC segments by assuming that the tracks
2490// are sufficiently stiff we are better served by something closer to a
2491// "straight-line" approximation
2492bool DTrackCandidate_factory::MatchMethod10(unsigned int src_index,
2493 const DTrackCandidate *srccan,
2494 const DFDCSegment *segment,
2495 vector<const DTrackCandidate*>&cands,
2496 vector<int> &forward_matches){
2497 if (DEBUG_LEVEL>0){
2498 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2498<<" "
<< "Attempting Match method #10..." << endl;
2499 }
2500 double q=srccan->charge();
2501 int pack1=segment->package;
2502
2503 // Get hits from segment and redo fit
2504 DHelicalFit fit1;
2505 for (unsigned int n=0;n<segment->hits.size();n++){
2506 const DFDCPseudo *hit=segment->hits[n];
2507 fit1.AddHit(hit);
2508 }
2509 fit1.FitCircleStraightTrack();
2510
2511 // Sense of rotation
2512 fit1.h=q*FactorForSenseOfRotation;
2513
2514 // Use the fdc track candidate to get tanl
2515 double theta=srccan->momentum().Theta();
2516 fit1.tanl=tan(M_PI_21.57079632679489661923-theta);
2517
2518 // Find the magnetic field at the first hit in the first segment
2519 double x=segment->hits[0]->xy.X();
2520 double y=segment->hits[0]->xy.Y();
2521 double z=segment->hits[0]->wire->origin.z();
2522 double Bz=fabs(bfield->GetBz(x,y,z));
2523
2524 // Get position and momentum for the first segment
2525 DVector3 mypos,mymom;
2526 GetPositionAndMomentum(z,fit1,Bz,mypos,mymom);
2527
2528 // Loop over the rest of the fdc track candidates, skipping those that have
2529 // already been used
2530 for (unsigned int k=src_index+1;k<forward_matches.size();k++){
2531 if (forward_matches[k]==0){
2532 const DTrackCandidate *can2=cands[k];
2533 // Get the segment data
2534 vector<const DFDCSegment *>segments2;
2535 can2->GetT(segments2);
2536
2537 int pack2=segments2[0]->package;
2538 if (abs(pack1-pack2)>0){
2539 // Get hits from the second segment and redo fit
2540 DHelicalFit fit2;
2541 for (unsigned int n=0;n<segments2[0]->hits.size();n++){
2542 const DFDCPseudo *hit=segments2[0]->hits[n];
2543 fit2.AddHit(hit);
2544 }
2545 fit2.FitCircleStraightTrack();
2546
2547 // Sense of rotation
2548 double q2=can2->charge();
2549 fit2.h=q2*FactorForSenseOfRotation;
2550
2551 // Use the fdc track candidate to get tanl
2552 theta=can2->momentum().Theta();
2553 fit2.tanl=tan(M_PI_21.57079632679489661923-theta);
2554
2555 // Try to match segments by swimming through the field
2556 if (MatchMethod11(q,mypos,mymom,fit2,segment,segments2[0])){
2557 forward_matches[k]=1;
2558 forward_matches[src_index]=1;
2559
2560 // Create a new DTrackCandidate for output
2561 DTrackCandidate *can = new DTrackCandidate;
2562
2563 // variables for finding <Bz>
2564 double Bz=0;
2565 int num_hits=0;
2566
2567 // Add hits from first segment as associated objects
2568 for (unsigned int n=0;n<segment->hits.size();n++){
2569 const DFDCPseudo *fdchit=segment->hits[n];
2570 can->AddAssociatedObject(fdchit);
2571
2572 Bz+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),
2573 fdchit->wire->origin.z());
2574 num_hits++;
2575 }
2576
2577 // Add the hits from the second segment to the first fit object
2578 // and refit the circle. Also add them as associated objects
2579 // to the new candidate.
2580 for (unsigned int n=0;n<segments2[0]->hits.size();n++){
2581 const DFDCPseudo *hit=segments2[0]->hits[n];
2582 fit1.AddHit(hit);
2583 can->AddAssociatedObject(hit);
2584
2585 Bz+=bfield->GetBz(hit->xy.X(),hit->xy.Y(),
2586 hit->wire->origin.z());
2587 num_hits++;
2588 }
2589 Bz=fabs(Bz)/double(num_hits);
2590
2591 // Initialize variables needed for output
2592 DVector3 mom=srccan->momentum();
2593 DVector3 pos=srccan->position();
2594 double q=srccan->charge();
2595 can->Ndof=srccan->Ndof;
2596 can->chisq=srccan->chisq;
2597
2598 if (fit1.FitCircleRiemann(fit1.r0)==NOERROR){
2599 can->Ndof=fit1.ndof;
2600 can->chisq=fit1.chisq;
2601
2602 // Redo line fit
2603 fit1.FitLineRiemann();
2604
2605 double p=0.003*fit1.r0*Bz/cos(atan(fit1.tanl));
2606 if (p>10.){
2607 // unphysical momentum, try alternate circle fit...
2608 fit1.FitCircle();
2609 }
2610
2611 // Guess charge from fit
2612 fit1.h=GetSenseOfRotation(fit1,segments2[0]->hits[0],
2613 srccan->position());
2614 q=FactorForSenseOfRotation*fit1.h;
2615
2616 // put z position just upstream of the first hit in z
2617 const DHFHit_t *myhit=fit1.GetHits()[0];
2618 pos.SetXYZ(myhit->x,myhit->y,myhit->z);
2619 GetPositionAndMomentum(myhit->z-1.,fit1,Bz,pos,mom);
2620 }
2621 // circle parameters
2622 can->rc=fit1.r0;
2623 can->xc=fit1.x0;
2624 can->yc=fit1.y0;
2625
2626 can->setPID((q > 0.0) ? PiPlus : PiMinus);
2627 can->setPosition(pos);
2628 can->setMomentum(mom);
2629
2630 trackcandidates.push_back(can);
2631
2632 if (DEBUG_LEVEL>0){
2633 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2633<<" "
<< "Match method #10 succeeded..." << endl;
2634 }
2635 return true;
2636 } // minimum number of matching hits
2637 } // different packages?
2638 } // already matched?
2639 } // loop over tracks
2640
2641 return false;
2642}
2643
2644// Swims from one FDC segment to another segment looking for a match. If this
2645// fails, swims from the second second to the first in the opposite direction.
2646bool DTrackCandidate_factory::MatchMethod11(double q,DVector3 &mypos,
2647 DVector3 &mymom,
2648 DHelicalFit &fit2,
2649 const DFDCSegment *segment1,
2650 const DFDCSegment *segment2
2651 ){
2652 if (DEBUG_LEVEL>0){
2653 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2653<<" "
<< "Attempting Match method #11..." << endl;
2654 }
2655
2656 // Package numbers
2657 int pack1=segment1->package;
2658 int pack2=segment2->package;
2659
2660 // Set direction of propagation for traversing from segment1 to segment2
2661 if ((pack2<pack1 && mymom.z()>0.) || (pack1>pack2 && mymom.z()<0.)) mymom=(-1.)*mymom;
2662
2663 // Find the magnetic field at the first hit of the second segment
2664 double x=segment2->hits[0]->xy.X();
2665 double y=segment2->hits[0]->xy.Y();
2666 double z=segment2->hits[0]->wire->origin.z();
2667
2668 double Bz=fabs(bfield->GetBz(x,y,z));
2669
2670 // Make local copies of input momentum and position
2671 DVector3 mymom1(mymom);
2672 DVector3 mypos1(mypos);
2673
2674 // Get position and momentum for the second segment
2675 DVector3 mypos2,mymom2;
2676 GetPositionAndMomentum(z,fit2,Bz,mypos2,mymom2);
2677
2678 if (pack2>pack1) mymom2=(-1.)*mymom2;
2679
2680 // Swim from the first segment to the second segment using the stepper
2681 const DFDCPseudo *secondhit=segment2->hits[0];
2682 DVector3 norm(0.,0.,1.);
2683 stepper->SetCharge(q);
2684 stepper->SwimToPlane(mypos1,mymom1,secondhit->wire->origin,norm,NULL__null);
2685
2686 // _DBG_<< endl;
2687 double variance=1.;
2688 if (mypos1.Perp()<48.5){
2689 // Look for match at first hit
2690 double dx=mypos1.x()-secondhit->xy.X();
2691 double dy=mypos1.y()-secondhit->xy.Y();
2692 double d2=dx*dx+dy*dy;
2693 double prob=TMath::Prob(d2/variance,1);
2694
2695 unsigned int num_match=(prob>0.01)?1:0;
2696
2697 // Try to match more hits
2698 for (unsigned int i=1;i<segment2->hits.size();i++){
2699 const DFDCPseudo *hit=segment2->hits[i];
2700
2701 if (mypos1.Perp()<48.5){
2702 ProjectHelixToZ(hit->wire->origin.z(),q,mymom1,mypos1);
2703
2704 DVector2 XY=hit->xy;
2705 double dx=XY.X()-mypos1.x();
2706 double dy=XY.Y()-mypos1.y();
2707 double dr2=dx*dx+dy*dy;
2708
2709 double variance=1.0;
2710 double prob = isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
2711 if (prob>0.01) num_match++;
2712 }
2713 }
2714 if (num_match>=3){
2715 if (DEBUG_LEVEL>0){
2716 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2716<<" "
<< "Method 11: found match!" << endl;
2717 }
2718 return true;
2719 }
2720 }
2721
2722 // Try swimming in opposite direction
2723 secondhit=segment1->hits[0];
2724
2725 double q2=fit2.h*FactorForSenseOfRotation;
2726 stepper->SetCharge(q2);
2727 stepper->SwimToPlane(mypos2,mymom2,secondhit->wire->origin,norm,NULL__null);
2728 // _DBG_ << mypos2.x() << " " << mypos2.y() << endl;
2729 if (mypos2.Perp()<48.5){
2730 // Look for match at first hit
2731 double dx=mypos2.x()-secondhit->xy.X();
2732 double dy=mypos2.y()-secondhit->xy.Y();
2733 double d2=dx*dx+dy*dy;
2734
2735 double prob=TMath::Prob(d2/variance,1);
2736
2737 unsigned int num_match=(prob>0.01)?1:0;
2738
2739 // Try to match more hits
2740 for (unsigned int i=1;i<segment1->hits.size();i++){
2741 const DFDCPseudo *hit=segment1->hits[i];
2742
2743 if (mypos2.Perp()<48.5){
2744 ProjectHelixToZ(hit->wire->origin.z(),q2,mymom2,mypos2);
2745
2746 DVector2 XY=hit->xy;
2747 double dx=XY.X()-mypos2.x();
2748 double dy=XY.Y()-mypos2.y();
2749 double dr2=dx*dx+dy*dy;
2750
2751 double variance=1.0;
2752 double prob = isfinite(dr2) ? TMath::Prob(dr2/variance,1):0.0;
2753 if (prob>0.01) num_match++;
2754 }
2755 }
2756 if (num_match>=3){
2757 if (DEBUG_LEVEL>0){
2758 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2758<<" "
<< "Method 11: found match!" << endl;
2759 }
2760 return true;
2761 }
2762 }
2763
2764 return false;
2765}
2766
2767
2768// Match low momentum track candidates using circle centers and radii of
2769// curvature
2770bool DTrackCandidate_factory::MatchMethod12(DTrackCandidate *can,
2771 vector<int> &forward_matches,
2772 int &num_fdc_cands_remaining){
2773 if (DEBUG_LEVEL>0){
2774 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2774<<" "
<< "Attempting matching method #12..." <<endl;
2775 }
2776 for (unsigned int i=0;i<fdctrackcandidates.size();i++){
2777 if (num_fdc_cands_remaining==0) return false;
2778 if (forward_matches[i]) continue;
2779
2780 const DTrackCandidate *fdccan = fdctrackcandidates[i];
2781 if (fdccan->momentum().Mag()>0.5) continue;
2782
2783 // Find how close the circle centers are to each other
2784 double dx=can->xc-fdccan->xc;
2785 double dy=can->yc-fdccan->yc;
2786 double dr2=dx*dx+dy*dy;
2787 // Require circle centers, radii and angles to agree at a reasonable level
2788 if (dr2<4.0 && fabs((can->rc-fdccan->rc)/can->rc)<0.5
2789 && fabs(can->momentum().Theta()-fdccan->momentum().Theta())<0.35 // 20 degrees
2790 ){
2791 // Get the segments belonging to the fdc candidate
2792 vector<const DFDCSegment *>segments;
2793 fdccan->GetT(segments);
2794 stable_sort(segments.begin(), segments.end(), SegmentSortByLayerincreasing);
2795
2796 // Get the hits from the input candidate
2797 vector<const DFDCPseudo*>myfdchits;
2798 can->GetT(myfdchits);
2799 if (myfdchits.size()>0){
2800 stable_sort(myfdchits.begin(),myfdchits.end(),FDCHitSortByLayerincreasing);
2801 unsigned int last_package
2802 =(myfdchits[myfdchits.size()-1]->wire->layer-1)/6;
2803 // look for something downstream...
2804 if (segments[0]->package-last_package==1){
2805 vector<const DCDCTrackHit *>cdchits;
2806 can->GetT(cdchits);
2807 stable_sort(cdchits.begin(), cdchits.end(), CDCHitSortByLayerincreasing);
2808 // Variables for computing average Bz
2809 double Bz=0;
2810 unsigned int num_hits=0;
2811
2812 // Instantiate the helical fitter to do the refit
2813 DHelicalFit fit;
2814 // Add CDC axial hits
2815 for (unsigned int k=0;k<cdchits.size();k++){
2816 if (cdchits[k]->is_stereo==false){
2817 double cov=0.213; //guess
2818 const DVector3 origin=cdchits[k]->wire->origin;
2819 double x=origin.x(),y=origin.y(),z=origin.z();
2820 fit.AddHitXYZ(x,y,z,cov,cov,0.,true);
2821 }
2822 }
2823 // Add the FDC hits and estimate Bz
2824 for (unsigned int k=0;k<segments.size();k++){
2825 for (unsigned int n=0;n<segments[k]->hits.size();n++){
2826 const DFDCPseudo *fdchit=segments[k]->hits[n];
2827 fit.AddHit(fdchit);
2828 //bfield->GetField(x,y,z,Bx,By,Bz);
2829 //Bz_avg-=Bz;
2830 Bz+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),fdchit->wire->origin.z());
2831 }
2832 num_hits+=segments[k]->hits.size();
2833 }
2834 for (unsigned int k=0;k<myfdchits.size();k++){
2835 const DFDCPseudo *fdchit=myfdchits[k];
2836 fit.AddHit(fdchit);
2837 //bfield->GetField(x,y,z,Bx,By,Bz);
2838 //Bz_avg-=Bz;
2839 Bz+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),fdchit->wire->origin.z());
2840 }
2841 num_hits+=myfdchits.size();
2842 Bz=fabs(Bz)/double(num_hits);
2843
2844 // Do the circle fit with all of the matched FDC hits
2845 if (fit.FitCircleRiemann(segments[0]->rc)==NOERROR){
2846 // Determine the polar angle
2847 double theta=fdccan->momentum().Theta();
2848 double theta_cdc=can->momentum().Theta();
2849 if (segments.size()==1 && theta_cdc<M_PI_40.78539816339744830962){
2850 double numcdc=double(cdchits.size());
2851 double numfdc=segments[0]->hits.size();
2852 theta=(theta*numfdc+theta_cdc*numcdc)/(numfdc+numcdc);
2853 }
2854 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
2855 // Redo the line fit
2856 fit.FitLineRiemann();
2857
2858 DVector3 myorigin;
2859 if (myfdchits.size()) myorigin.SetXYZ(myfdchits[0]->xy.X(),
2860 myfdchits[0]->xy.Y(),
2861 myfdchits[0]->wire->origin.z());
2862 if (cdchits.size()) myorigin=cdchits[0]->wire->origin;
2863 DVector3 pos=fdccan->position(),mom;
2864 UpdatePositionAndMomentum(fit,Bz,myorigin,pos,mom);
2865
2866 // circle parameters
2867 can->rc=fit.r0;
2868 can->xc=fit.x0;
2869 can->yc=fit.y0;
2870
2871 // Add additional fdc hits to the track as associated objects
2872 for (unsigned int m=0;m<segments.size();m++){
2873 for (unsigned int n=0;n<segments[m]->hits.size();n++){
2874 can->AddAssociatedObject(segments[m]->hits[n]);
2875 }
2876 }
2877 can->chisq=fit.chisq;
2878 can->Ndof=fit.ndof;
2879 Particle_t locPID = (FactorForSenseOfRotation*fit.h > 0.0) ? PiPlus : PiMinus;
2880 can->setPID(locPID);
2881 can->setMomentum(mom);
2882 can->setPosition(pos);
2883
2884 forward_matches[i]=1;
2885 num_fdc_cands_remaining--;
2886
2887 if (DEBUG_LEVEL>0){
2888 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2888<<" "
<< "... Found match!" << endl;
2889 }
2890 return true;
2891 } // circle fit
2892 } // look for packages downstream of those attached to candidate
2893 } // if we have fdc hits in the existing track candidate
2894 else{
2895 // Get the cdc hits belonging to the track
2896 vector<const DCDCTrackHit *>cdchits;
2897 can->GetT(cdchits);
2898 stable_sort(cdchits.begin(), cdchits.end(), CDCHitSortByLayerincreasing);
2899
2900 // Variables for computing average Bz
2901 double Bz=0;
2902 unsigned int num_hits=0;
2903
2904 // Instantiate the helical fitter to do the refit
2905 DHelicalFit fit;
2906 // Add CDC axial hits
2907 for (unsigned int k=0;k<cdchits.size();k++){
2908 if (cdchits[k]->is_stereo==false){
2909 double cov=0.213; //guess
2910 const DVector3 origin=cdchits[k]->wire->origin;
2911 double x=origin.x(),y=origin.y(),z=origin.z();
2912 fit.AddHitXYZ(x,y,z,cov,cov,0.,true);
2913 }
2914 }
2915 // Add the FDC hits and estimate Bz
2916 for (unsigned int k=0;k<segments.size();k++){
2917 for (unsigned int n=0;n<segments[k]->hits.size();n++){
2918 const DFDCPseudo *fdchit=segments[k]->hits[n];
2919 fit.AddHit(fdchit);
2920 //bfield->GetField(x,y,z,Bx,By,Bz);
2921 //Bz_avg-=Bz;
2922 Bz+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),fdchit->wire->origin.z());
2923 }
2924 num_hits+=segments[k]->hits.size();
2925 }
2926 Bz=fabs(Bz)/double(num_hits);
2927
2928 // Do the circle fit with all of the matched FDC hits
2929 if (fit.FitCircleRiemann(segments[0]->rc)==NOERROR){
2930 // Determine the polar angle
2931 double theta=fdccan->momentum().Theta();
2932 double theta_cdc=can->momentum().Theta();
2933 if (segments.size()==1 && theta_cdc<M_PI_40.78539816339744830962){
2934 double numcdc=double(cdchits.size());
2935 double numfdc=segments[0]->hits.size();
2936 theta=(theta*numfdc+theta_cdc*numcdc)/(numfdc+numcdc);
2937 }
2938 // recompute position and momentum
2939 fit.tanl=tan(M_PI_21.57079632679489661923-theta);
2940 DVector3 myorigin=cdchits[0]->wire->origin;
2941 DVector3 pos=fdccan->position(),mom;
2942 UpdatePositionAndMomentum(fit,Bz,cdchits[0]->wire->origin,pos,mom);
2943
2944 // circle parameters
2945 can->rc=fit.r0;
2946 can->xc=fit.x0;
2947 can->yc=fit.y0;
2948
2949 // Add additional fdc hits to the track as associated objects
2950 for (unsigned int m=0;m<segments.size();m++){
2951 for (unsigned int n=0;n<segments[m]->hits.size();n++){
2952 can->AddAssociatedObject(segments[m]->hits[n]);
2953 }
2954 }
2955
2956 can->setPosition(pos);
2957 can->chisq=fit.chisq;
2958 can->Ndof=fit.ndof;
2959 Particle_t locPID = (FactorForSenseOfRotation*fit.h > 0.0) ? PiPlus : PiMinus;
2960 can->setPID(locPID);
2961 can->setMomentum(mom);
2962
2963 forward_matches[i]=1;
2964 num_fdc_cands_remaining--;
2965
2966 if (DEBUG_LEVEL>0){
2967 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2967<<" "
<< "... Found match!" << endl;
2968 }
2969 return true;
2970 } // circle fit worked
2971 }
2972 } // matching criteria
2973 } // loop over existing track candidates
2974
2975 return false;
2976}
2977
2978// Attempts to match two single-segment track candidates by only using the
2979// hit information to fit circles (i.e., not requiring the tracks to originate
2980// from the target region.) The idea is to recover some tracks arising from
2981// secondary interactions or decays beyond the target.
2982bool DTrackCandidate_factory::MatchMethod13(unsigned int src_index,
2983 const DTrackCandidate *srccan,
2984 const DFDCSegment *segment,
2985 vector<const DTrackCandidate*>&cands,
2986 vector<int> &forward_matches){
2987 if (DEBUG_LEVEL>0){
2988 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<2988<<" "
<< "Attempting Match method #13..." << endl;
2989 }
2990 double q=srccan->charge();
2991 int pack1=segment->package;
2992
2993 // Get hits from segment and redo fit
2994 DHelicalFit fit1;
2995 for (unsigned int n=0;n<segment->hits.size();n++){
2996 const DFDCPseudo *hit=segment->hits[n];
2997 fit1.AddHit(hit);
2998 }
2999
3000 if (fit1.FitCircleRiemann(srccan->rc)!=NOERROR) return false;
3001
3002 // Guess for theta and z from input candidates
3003 double theta=srccan->momentum().Theta();
3004 fit1.tanl=tan(M_PI_21.57079632679489661923-theta);
3005 fit1.z_vertex=srccan->position().Z();
3006
3007 // Redo line fit
3008 if (fit1.FitLineRiemann()!=NOERROR) return false;
3009
3010 // Find the magnetic field at the first hit in the first segment
3011 double x=segment->hits[0]->xy.X();
3012 double y=segment->hits[0]->xy.Y();
3013 double z=segment->hits[0]->wire->origin.z();
3014 double Bz=fabs(bfield->GetBz(x,y,z));
3015
3016 // Get position and momentum for the first segment
3017 DVector3 mypos,mymom;
3018 GetPositionAndMomentum(z,fit1,Bz,mypos,mymom);
3019
3020 // Loop over the rest of the fdc track candidates, skipping those that have
3021 // already been used
3022 for (unsigned int k=src_index+1;k<forward_matches.size();k++){
3023 if (forward_matches[k]==0){
3024 const DTrackCandidate *can2=fdctrackcandidates[k];
3025 // Get the segment data
3026 vector<const DFDCSegment *>segments2;
3027 can2->GetT(segments2);
3028
3029 int pack2=segments2[0]->package;
3030 if (abs(pack1-pack2)>0){
3031 // Get hits from the second segment and redo fit
3032 DHelicalFit fit2;
3033 for (unsigned int n=0;n<segments2[0]->hits.size();n++){
3034 const DFDCPseudo *hit=segments2[0]->hits[n];
3035 fit2.AddHit(hit);
3036 }
3037
3038 if (fit2.FitCircleRiemann(segments2[0]->rc)!=NOERROR) continue;
3039
3040 // Guess for theta and z from input candidates
3041 theta=can2->momentum().Theta();
3042 fit2.tanl=tan(M_PI_21.57079632679489661923-theta);
3043 fit2.z_vertex=srccan->position().Z();
3044
3045 // Redo line fit
3046 if (fit2.FitLineRiemann()!=NOERROR) continue;
3047
3048 // Try to match segments by swimming through the field
3049 if (MatchMethod11(q,mypos,mymom,fit2,segment,segments2[0])){
3050 forward_matches[k]=1;
3051 forward_matches[src_index]=1;
3052
3053 // Create a new DTrackCandidate for output
3054 DTrackCandidate *can = new DTrackCandidate;
3055
3056 // variables for finding <Bz>
3057 double Bz=0;
3058 int num_hits=0;
3059
3060 // Add hits from first segment as associated objects
3061 for (unsigned int n=0;n<segment->hits.size();n++){
3062 const DFDCPseudo *fdchit=segment->hits[n];
3063 can->AddAssociatedObject(fdchit);
3064
3065 Bz+=bfield->GetBz(fdchit->xy.X(),fdchit->xy.Y(),
3066 fdchit->wire->origin.z());
3067 num_hits++;
3068 }
3069
3070 // Add the hits from the second segment to the first fit object
3071 // and refit the circle. Also add them as associated objects
3072 // to the new candidate.
3073 for (unsigned int n=0;n<segments2[0]->hits.size();n++){
3074 const DFDCPseudo *hit=segments2[0]->hits[n];
3075 fit1.AddHit(hit);
3076 can->AddAssociatedObject(hit);
3077
3078 Bz+=bfield->GetBz(hit->xy.X(),hit->xy.Y(),
3079 hit->wire->origin.z());
3080 num_hits++;
3081 }
3082 Bz=fabs(Bz)/double(num_hits);
3083
3084 // Initialize variables needed for output
3085 DVector3 mom=srccan->momentum();
3086 DVector3 pos=srccan->position();
3087 double q=srccan->charge();
3088 can->Ndof=srccan->Ndof;
3089 can->chisq=srccan->chisq;
3090
3091 if (fit1.FitCircleRiemann(fit1.r0)==NOERROR){
3092 can->Ndof=fit1.ndof;
3093 can->chisq=fit1.chisq;
3094
3095 // Redo line fit
3096 fit1.FitLineRiemann();
3097
3098 // Guess charge from fit
3099 fit1.h=GetSenseOfRotation(fit1,segments2[0]->hits[0],
3100 srccan->position());
3101 q=FactorForSenseOfRotation*fit1.h;
3102
3103 // put z position just upstream of the first hit in z
3104 const DHFHit_t *myhit=fit1.GetHits()[0];
3105 pos.SetXYZ(myhit->x,myhit->y,myhit->z);
3106 GetPositionAndMomentum(myhit->z-1.,fit1,Bz,pos,mom);
3107 }
3108 // circle parameters
3109 can->rc=fit1.r0;
3110 can->xc=fit1.x0;
3111 can->yc=fit1.y0;
3112
3113 can->setPID((q > 0.0) ? PiPlus : PiMinus);
3114 can->setPosition(pos);
3115 can->setMomentum(mom);
3116
3117 trackcandidates.push_back(can);
3118
3119 if (DEBUG_LEVEL>0){
3120 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<3120<<" "
<< "Match method #13 succeeded..." << endl;
3121 }
3122 return true;
3123 } // minimum number of matching hits
3124 } // different packages?
3125 } // already matched?
3126 } // loop over tracks
3127
3128 return false;
3129}
3130
3131// Routine to return momentum and position given the helical parameters and the
3132// z-component of the magnetic field
3133void
3134DTrackCandidate_factory::GetPositionAndMomentum(double z,const DHelicalFit &fit,
3135 double Bz,DVector3 &pos,
3136 DVector3 &mom) const{
3137 double xc=fit.x0;
3138 double yc=fit.y0;
3139 double rc=fit.r0;
3140 // Position
3141 double phi1=atan2(pos.y()-yc,pos.x()-xc);
3142 double q_over_rc_tanl=FactorForSenseOfRotation*fit.h/(rc*fit.tanl);
3143 double dphi_s=(pos.z()-z)*q_over_rc_tanl;
3144 double dphi1=phi1-dphi_s;// was -
3145 double x=xc+rc*cos(dphi1);
3146 double y=yc+rc*sin(dphi1);
3147 pos.SetXYZ(x,y,z);
3148
3149 dphi1*=-1.;
3150 if (fit.h<0) dphi1+=M_PI3.14159265358979323846;
3151
3152 // Momentum
3153 double pt=0.003*fabs(Bz)*rc;
3154 double px=pt*sin(dphi1);
3155 double py=pt*cos(dphi1);
3156 double pz=pt*fit.tanl;
3157 mom.SetXYZ(px,py,pz);
3158}
3159
3160// Use information from the start counter to try to correct the momentum and
3161// position for tracks seem to be pointing backwards but are probably pointing
3162// forwards. In these cases the circle projection intersects with a start
3163// counter paddle but the z-position at the radius r just outside the start
3164// counter barrel region is downstream of the nose, which does not make
3165// sense for a particle that is actually heading upstream...
3166bool DTrackCandidate_factory::TryToFlipDirection(vector<const DSCHit *>&schits,
3167 DVector3 &mom,DVector3 &pos) const{
3168 if (schits.size()==0) return false;
3169 if (DEBUG_LEVEL>0){
3170 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<3170<<" "
<< "Attempting to flip direction of track..." << endl;
3171 }
3172
3173 double zsc=sc_pos[0][1].z();
3174 if (pos.z()>zsc){
3175 unsigned int best_sc_sector_id=0;
3176 double dphi_min=1000.;
3177 double cand_phi=pos.Phi();
3178 for (unsigned int k=0;k<schits.size();k++){
3179 unsigned int sector_id=schits[k]->sector-1;
3180 double dphi=cand_phi-sc_pos[sector_id][0].Phi();
3181 if (dphi<-M_PI3.14159265358979323846) dphi+=2.*M_PI3.14159265358979323846;
3182 if (dphi>M_PI3.14159265358979323846) dphi-=2.*M_PI3.14159265358979323846;
3183
3184 if (fabs(dphi)<dphi_min){
3185 best_sc_sector_id=sector_id;
3186 dphi_min=fabs(dphi);
3187 }
3188 }
3189 if (dphi_min<0.105){
3190 // simplest approach: just change the direction -z -> +z
3191 mom.SetMagThetaPhi(mom.Mag(),M_PI3.14159265358979323846-mom.Theta(),mom.Phi());
3192 pos=sc_pos[best_sc_sector_id][1];
3193 // _DBG_ << " Event " << eventnumber << endl;
3194 if (DEBUG_LEVEL>0){
3195 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<3195<<" "
<< "Changing direction of CDC candidate..." << endl;
3196 }
3197 return true;
3198 }
3199 }
3200
3201
3202 return false;
3203}
3204
3205// Last ditch attempt to match stray segments in the FDC to other track stubs
3206// after all other matching techniques have been tried...
3207bool DTrackCandidate_factory::MatchStraySegments(vector<int> &forward_matches,
3208 int &num_fdc_cands_remaining){
3209 if (DEBUG_LEVEL>0){
3210 _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<3210<<" "
<< "Attempting to match stray FDC segments..." << endl;
3211 }
3212
3213 bool got_new_match=false;
3214 for (unsigned int j=0;j<forward_matches.size();j++){
3215 if (num_fdc_cands_remaining==0) break;
3216 if (forward_matches[j]==0){
3217 const DTrackCandidate *srccan=fdctrackcandidates[j];
3218
3219 // Get the segment data
3220 vector<const DFDCSegment *>segments;
3221 srccan->GetT(segments);
3222 const DFDCSegment *segment=segments[0];
3223
3224 // redo circle fits for segments, forcing the circles to go through (0,0)
3225 if (MatchMethod9(j,srccan,segment,fdctrackcandidates,forward_matches)){
3226 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<3226<<" "
<< "Matched FDC segments using method #9" << endl;
3227 num_fdc_cands_remaining-=2;
3228 got_new_match=true;
3229 }
3230 // Redo circle fit assuming track is almost straight
3231 else if (MatchMethod10(j,srccan,segment,fdctrackcandidates,
3232 forward_matches)){
3233 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<3233<<" "
<< "Matched FDC segments using method #10" << endl;
3234 num_fdc_cands_remaining-=2;
3235 got_new_match=true;
3236 }
3237 // Redo circle fits without any assumption that the tracks originate
3238 // from the target
3239 else if (MatchMethod13(j,srccan,segment,fdctrackcandidates,
3240 forward_matches)){
3241 if (DEBUG_LEVEL>0) _DBG_std::cerr<<"libraries/TRACKING/DTrackCandidate_factory.cc"
<<":"<<3241<<" "
<< "Matched FDC segments using method #13" << endl;
3242 num_fdc_cands_remaining-=2;
3243 got_new_match=true;
3244 }
3245 } // not already matched
3246 }
3247 return got_new_match;
3248}
3249
3250// Routine for updating the position and radius given an input position pos.
3251// If the circle from the track intersects the circle with a radius just outside
3252// the start counter, returns the position and momentum at the place where the
3253// two circles intersect. If the two circles do not intersect, returns the
3254// position at the doca to the beam line. If the z position is far upstream
3255// of the active volume for either case, places the position at z=0.
3256void DTrackCandidate_factory::UpdatePositionAndMomentum(DHelicalFit &fit,
3257 double Bz,
3258 const DVector3 &origin,
3259 DVector3 &pos,
3260 DVector3 &mom) const{
3261 // Get position at fixed radius with respect to the beam line
3262 if (GetPositionAndMomentum(fit,Bz,origin,pos,mom)!=NOERROR){
3263 // Get position and momentum at doca to beam line
3264 GetPositionAndMomentum(fit,Bz,pos,mom);
3265 }
3266 // if the z-position is far away from the active volume of the detector,
3267 // place position at fixed z=0.
3268 if (pos.z()<0){
3269 GetPositionAndMomentum(0.,fit,Bz,pos,mom);
3270 }
3271}
3272
3273// Returns false if the z position at the doca to the beam line is less than 0
3274bool DTrackCandidate_factory::CheckZPosition(const DTrackCandidate *fdccan)
3275 const{
3276 double phi0=atan2(-fdccan->xc,fdccan->yc);
3277 double q=fdccan->charge();
3278 if (FactorForSenseOfRotation*q<0) phi0+=M_PI3.14159265358979323846;
3279 double sinphi0=sin(phi0);
3280 double sign=(sinphi0>0)?1.:-1.;
3281 if (fabs(sinphi0)<1e-8) sinphi0=sign*1e-8;
3282 double D=q*fdccan->rc-fdccan->xc/sinphi0;
3283 double x=-D*sinphi0;
3284 double y=D*cos(phi0);
3285 DVector3 pos=fdccan->position();
3286 double dx=pos.x()-x;
3287 double dy=pos.y()-y;
3288 double ratio=sqrt(dx*dx+dy*dy)/(2.*fdccan->rc);
3289 double phi_s=(ratio<1.)?2.*asin(ratio):M_PI3.14159265358979323846;
3290 double newz=pos.z()-phi_s*tan(M_PI_21.57079632679489661923-fdccan->momentum().Theta())*fdccan->rc;
3291
3292 return (newz>0);
3293}
3294
3295

/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);
6
Calling 'JEventLoop::Get'
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
6.1
'tag' is not equal to NULL
6.1
'tag' is not equal to NULL
6.1
'tag' is not equal to NULL
==NULL__null ? "":tag; // protection against NULL tags
7
'?' condition is false
291 if(strlen(mytag)==0 && allow_deftag
7.1
'allow_deftag' is true
7.1
'allow_deftag' is true
7.1
'allow_deftag' is true
){
8
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();
9
Assuming the condition is true
10
Taking true branch
11
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);
12
Assuming field 'record_call_stack' is false
13
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);
14
Passing value via 2nd parameter 'tag'
15
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
16
Assuming 'tag' is equal to NULL
17
Assuming pointer value is null
18
'?' condition is true
380 if(strlen(mytag)==0 && allow_deftag
18.1
'allow_deftag' is true
18.1
'allow_deftag' is true
18.1
'allow_deftag' is true
){
19
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();
20
Assuming the condition is false
21
Taking false branch
383 }
384
385 for(; iter!=factories.end(); iter++){
22
Calling 'operator!=<jana::JFactory_base **, std::vector<jana::JFactory_base *>>'
25
Returning from 'operator!=<jana::JFactory_base **, std::vector<jana::JFactory_base *>>'
26
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);
27
Taking true branch
396 if(factory == NULL__null)continue;
28
Assuming 'factory' is not equal to NULL
29
Taking false branch
397 const char *factag = factory->Tag()==NULL__null ? "":factory->Tag();
30
Assuming the condition is true
31
'?' condition is true
398 if(!strcmp(factag, tag)){
32
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(); }
23
Assuming the condition is true
24
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