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' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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> | ||||||
38 | using 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 | //------------------ | ||||||
59 | inline 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 | //------------------ | ||||||
73 | inline 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 | //------------------ | ||||||
87 | inline 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 | //------------------ | ||||||
104 | inline 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 | //------------------ | ||||||
120 | jerror_t DTrackCandidate_factory::init(void) | ||||||
121 | { | ||||||
122 | MAX_NUM_TRACK_CANDIDATES = 20; | ||||||
123 | |||||||
124 | return NOERROR; | ||||||
125 | } | ||||||
126 | |||||||
127 | //------------------ | ||||||
128 | // brun | ||||||
129 | //------------------ | ||||||
130 | jerror_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.; | ||||||
| |||||||
135 | |||||||
136 | // Get start counter geometry; | ||||||
137 | dgeom->GetStartCounterGeom(sc_pos,sc_norm); | ||||||
138 | |||||||
139 | dIsNoFieldFlag = (dynamic_cast<const DMagneticFieldMapNoField*>(bfield) != NULL__null); | ||||||
140 | if(dIsNoFieldFlag
| ||||||
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); | ||||||
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 | //------------------ | ||||||
214 | jerror_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 | //------------------ | ||||||
227 | jerror_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 | //------------------ | ||||||
242 | jerror_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. | ||||||
813 | void 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 | ||||||
850 | void 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 | ||||||
877 | jerror_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 | ||||||
961 | void 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 | ||||||
988 | double 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 | ||||||
1041 | double 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. | ||||||
1073 | jerror_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. | ||||||
1121 | bool 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 | ||||||
1184 | bool 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 | ||||||
1568 | bool 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. | ||||||
1738 | bool 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 | ||||||
1842 | void 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 | ||||||
1953 | bool 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. | ||||||
2122 | bool 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. | ||||||
2324 | bool 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 | ||||||
2492 | bool 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. | ||||||
2646 | bool 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 | ||||||
2770 | bool 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. | ||||||
2982 | bool 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 | ||||||
3133 | void | ||||||
3134 | DTrackCandidate_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... | ||||||
3166 | bool 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... | ||||||
3207 | bool 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. | ||||||
3256 | void 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 | ||||||
3274 | bool 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 |
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> | ||||||
21 | using std::vector; | ||||||
22 | using std::list; | ||||||
23 | using std::string; | ||||||
24 | using 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 | ||||||
42 | namespace jana{ | ||||||
43 | |||||||
44 | |||||||
45 | template<class T> class JFactory; | ||||||
46 | class JApplication; | ||||||
47 | class JEventProcessor; | ||||||
48 | |||||||
49 | |||||||
50 | class 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 | ||||||
215 | typedef JEventLoop::call_stack_t call_stack_t; | ||||||
216 | typedef JEventLoop::error_call_stack_t error_call_stack_t; | ||||||
217 | #endif | ||||||
218 | |||||||
219 | #if !defined(__CINT__) && !defined(__CLING__) | ||||||
220 | |||||||
221 | //------------- | ||||||
222 | // GetSingle | ||||||
223 | //------------- | ||||||
224 | template<class T> | ||||||
225 | JFactory<T>* JEventLoop::GetSingle(const T* &t, const char *tag, bool exception_if_not_one) | ||||||
226 | { | ||||||
227 | /// This is a convenience method that can be used to get a pointer to the single | ||||||
228 | /// object of type T from the specified factory. It simply calls the Get(vector<...>) method | ||||||
229 | /// and copies the first pointer into "t" (or NULL if something other than 1 object is returned). | ||||||
230 | /// | ||||||
231 | /// This is intended to address the common situation in which there is an interest | ||||||
232 | /// in the event if and only if there is exactly 1 object of type T. If the event | ||||||
233 | /// has no objects of that type or more than 1 object of that type (for the specified | ||||||
234 | /// factory) then an exception of type "unsigned long" is thrown with the value | ||||||
235 | /// being the number of objects of type T. You can supress the exception by setting | ||||||
236 | /// exception_if_not_one to false. In that case, you will have to check if t==NULL to | ||||||
237 | /// know if the call succeeded. | ||||||
238 | vector<const T*> v; | ||||||
239 | JFactory<T> *fac = Get(v, tag); | ||||||
240 | |||||||
241 | if(v.size()!=1){ | ||||||
242 | t = NULL__null; | ||||||
243 | if(exception_if_not_one) throw v.size(); | ||||||
244 | } | ||||||
245 | |||||||
246 | t = v[0]; | ||||||
247 | |||||||
248 | return fac; | ||||||
249 | } | ||||||
250 | |||||||
251 | //------------- | ||||||
252 | // Get | ||||||
253 | //------------- | ||||||
254 | template<class T> | ||||||
255 | JFactory<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
| ||||||
291 | if(strlen(mytag)==0 && allow_deftag
| ||||||
292 | map<string, string>::const_iterator iter = default_tags.find(T::static_className()); | ||||||
293 | if(iter!=default_tags.end())tag = iter->second.c_str(); | ||||||
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); | ||||||
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); | ||||||
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 | //------------- | ||||||
368 | template<class T> | ||||||
369 | JFactory<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 | ||||||
380 | if(strlen(mytag)==0 && allow_deftag
| ||||||
381 | map<string, string>::const_iterator iter = default_tags.find(className); | ||||||
382 | if(iter!=default_tags.end())tag = iter->second.c_str(); | ||||||
383 | } | ||||||
384 | |||||||
385 | for(; iter!=factories.end(); iter++){ | ||||||
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); | ||||||
396 | if(factory == NULL__null)continue; | ||||||
397 | const char *factag = factory->Tag()==NULL__null ? "":factory->Tag(); | ||||||
398 | if(!strcmp(factag, tag)){ | ||||||
| |||||||
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 | //------------- | ||||||
462 | template<class T> | ||||||
463 | jerror_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 | //------------- | ||||||
483 | inline 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 | //------------- | ||||||
504 | inline 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 | //------------- | ||||||
521 | inline 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 | //------------- | ||||||
556 | template<class T> | ||||||
557 | const 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 | //------------- | ||||||
589 | template<class T> | ||||||
590 | bool 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 | //------------- | ||||||
613 | template<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 | //------------- | ||||||
632 | template<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 | //------------- | ||||||
651 | template<class T> | ||||||
652 | bool 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 | //------------- | ||||||
675 | template<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 | //------------- | ||||||
692 | template<class T> | ||||||
693 | void 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 | //------------- | ||||||
702 | template<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 | //------------- | ||||||
716 | template<class T> | ||||||
717 | T* 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 | //------------- | ||||||
730 | template<class T> | ||||||
731 | vector<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 | //------------- | ||||||
746 | template<class T> | ||||||
747 | void 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 |
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 | |
67 | namespace 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 | |
694 | namespace __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(); } |
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 | |
911 | namespace 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 |