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: DTrackTimeBased_factory.cc | ||||||
4 | // Created: Thu Sep 4 14:02:44 EDT 2008 | ||||||
5 | // Creator: davidl (on Darwin harriet.jlab.org 8.11.1 i386) | ||||||
6 | // | ||||||
7 | |||||||
8 | |||||||
9 | #include <iostream> | ||||||
10 | #include <iomanip> | ||||||
11 | #include <set> | ||||||
12 | #include <mutex> | ||||||
13 | #include <TMath.h> | ||||||
14 | using namespace std; | ||||||
15 | |||||||
16 | #define TOF_SIGMA0.080 0.080 // TOF resolution in ns | ||||||
17 | |||||||
18 | #include <TROOT.h> | ||||||
19 | |||||||
20 | #include "DTrackTimeBased_factory.h" | ||||||
21 | #include <TRACKING/DTrackWireBased.h> | ||||||
22 | #include <TRACKING/DReferenceTrajectory.h> | ||||||
23 | #include <TRACKING/DTrackFitter.h> | ||||||
24 | #include <TRACKING/DTrackHitSelector.h> | ||||||
25 | #include <TRACKING/DMCTrackHit.h> | ||||||
26 | #include <SplitString.h> | ||||||
27 | #include "HDGEOMETRY/DMagneticFieldMapNoField.h" | ||||||
28 | #include <deque> | ||||||
29 | |||||||
30 | using namespace jana; | ||||||
31 | |||||||
32 | // Routine for sorting start times | ||||||
33 | bool DTrackTimeBased_T0_cmp(DTrackTimeBased::DStartTime_t a, | ||||||
34 | DTrackTimeBased::DStartTime_t b){ | ||||||
35 | return (a.system>b.system); | ||||||
36 | } | ||||||
37 | |||||||
38 | bool DTrackTimeBased_cmp(DTrackTimeBased *a,DTrackTimeBased *b){ | ||||||
39 | if (a->candidateid==b->candidateid) return a->mass()<b->mass(); | ||||||
40 | return a->candidateid<b->candidateid; | ||||||
41 | } | ||||||
42 | |||||||
43 | |||||||
44 | // count_common_members | ||||||
45 | //------------------ | ||||||
46 | template<typename T> | ||||||
47 | static unsigned int count_common_members(vector<T> &a, vector<T> &b) | ||||||
48 | { | ||||||
49 | unsigned int n=0; | ||||||
50 | for(unsigned int i=0; i<a.size(); i++){ | ||||||
51 | for(unsigned int j=0; j<b.size(); j++){ | ||||||
52 | if(a[i]==b[j])n++; | ||||||
53 | } | ||||||
54 | } | ||||||
55 | |||||||
56 | return n; | ||||||
57 | } | ||||||
58 | |||||||
59 | |||||||
60 | |||||||
61 | //------------------ | ||||||
62 | // init | ||||||
63 | //------------------ | ||||||
64 | jerror_t DTrackTimeBased_factory::init(void) | ||||||
65 | { | ||||||
66 | fitter = NULL__null; | ||||||
67 | |||||||
68 | DEBUG_HISTS = false; | ||||||
69 | //DEBUG_HISTS = true; | ||||||
70 | DEBUG_LEVEL = 0; | ||||||
71 | |||||||
72 | USE_HITS_FROM_WIREBASED_FIT=false; | ||||||
73 | gPARMS->SetDefaultParameter("TRKFIT:USE_HITS_FROM_WIREBASED_FIT", | ||||||
74 | USE_HITS_FROM_WIREBASED_FIT); | ||||||
75 | INSERT_MISSING_HYPOTHESES=true; | ||||||
76 | gPARMS->SetDefaultParameter("TRKFIT:INSERT_MISSING_HYPOTHESES", | ||||||
77 | INSERT_MISSING_HYPOTHESES); | ||||||
78 | |||||||
79 | gPARMS->SetDefaultParameter("TRKFIT:DEBUG_HISTS",DEBUG_HISTS); | ||||||
80 | gPARMS->SetDefaultParameter("TRKFIT:DEBUG_LEVEL",DEBUG_LEVEL); | ||||||
81 | |||||||
82 | vector<int> hypotheses; | ||||||
83 | hypotheses.push_back(Positron); | ||||||
84 | hypotheses.push_back(PiPlus); | ||||||
85 | hypotheses.push_back(KPlus); | ||||||
86 | hypotheses.push_back(Proton); | ||||||
87 | hypotheses.push_back(Electron); | ||||||
88 | hypotheses.push_back(PiMinus); | ||||||
89 | hypotheses.push_back(KMinus); | ||||||
90 | hypotheses.push_back(AntiProton); | ||||||
91 | |||||||
92 | ostringstream locMassStream; | ||||||
93 | for(size_t loc_i = 0; loc_i < hypotheses.size(); ++loc_i) | ||||||
94 | { | ||||||
95 | locMassStream << hypotheses[loc_i]; | ||||||
96 | if(loc_i != (hypotheses.size() - 1)) | ||||||
97 | locMassStream << ","; | ||||||
98 | } | ||||||
99 | |||||||
100 | string HYPOTHESES = locMassStream.str(); | ||||||
101 | gPARMS->SetDefaultParameter("TRKFIT:HYPOTHESES", HYPOTHESES); | ||||||
102 | |||||||
103 | // Parse MASS_HYPOTHESES strings to make list of masses to try | ||||||
104 | hypotheses.clear(); | ||||||
105 | SplitString(HYPOTHESES, hypotheses, ","); | ||||||
106 | for(size_t loc_i = 0; loc_i < hypotheses.size(); ++loc_i) | ||||||
107 | { | ||||||
108 | if(ParticleCharge(Particle_t(hypotheses[loc_i])) > 0){ | ||||||
109 | mass_hypotheses_positive.push_back(hypotheses[loc_i]); | ||||||
110 | } | ||||||
111 | else if(ParticleCharge(Particle_t(hypotheses[loc_i])) < 0){ | ||||||
112 | mass_hypotheses_negative.push_back(hypotheses[loc_i]); | ||||||
113 | } | ||||||
114 | } | ||||||
115 | |||||||
116 | if(mass_hypotheses_positive.empty()){ | ||||||
117 | static once_flag pwarn_flag; | ||||||
118 | call_once(pwarn_flag, [](){ | ||||||
119 | jout << endl; | ||||||
120 | jout << "############# WARNING !! ################ " <<endl; | ||||||
121 | jout << "There are no mass hypotheses for positive tracks!" << endl; | ||||||
122 | jout << "Be SURE this is what you really want!" << endl; | ||||||
123 | jout << "######################################### " <<endl; | ||||||
124 | jout << endl; | ||||||
125 | }); | ||||||
126 | } | ||||||
127 | if(mass_hypotheses_negative.empty()){ | ||||||
128 | static once_flag nwarn_flag; | ||||||
129 | call_once(nwarn_flag, [](){ | ||||||
130 | jout << endl; | ||||||
131 | jout << "############# WARNING !! ################ " <<endl; | ||||||
132 | jout << "There are no mass hypotheses for negative tracks!" << endl; | ||||||
133 | jout << "Be SURE this is what you really want!" << endl; | ||||||
134 | jout << "######################################### " <<endl; | ||||||
135 | jout << endl; | ||||||
136 | }); | ||||||
137 | } | ||||||
138 | |||||||
139 | mNumHypPlus=mass_hypotheses_positive.size(); | ||||||
140 | mNumHypMinus=mass_hypotheses_negative.size(); | ||||||
141 | |||||||
142 | // Forces correct particle id (when available) | ||||||
143 | PID_FORCE_TRUTH = false; | ||||||
144 | gPARMS->SetDefaultParameter("TRKFIT:PID_FORCE_TRUTH", PID_FORCE_TRUTH); | ||||||
145 | |||||||
146 | USE_SC_TIME=true; | ||||||
147 | gPARMS->SetDefaultParameter("TRKFIT:USE_SC_TIME",USE_SC_TIME); | ||||||
148 | |||||||
149 | USE_TOF_TIME=true; | ||||||
150 | gPARMS->SetDefaultParameter("TRKFIT:USE_TOF_TIME",USE_TOF_TIME); | ||||||
151 | |||||||
152 | USE_FCAL_TIME=true; | ||||||
153 | gPARMS->SetDefaultParameter("TRKFIT:USE_FCAL_TIME",USE_FCAL_TIME); | ||||||
154 | |||||||
155 | USE_BCAL_TIME=true; | ||||||
156 | gPARMS->SetDefaultParameter("TRKFIT:USE_BCAL_TIME",USE_BCAL_TIME); | ||||||
157 | |||||||
158 | return NOERROR; | ||||||
159 | } | ||||||
160 | |||||||
161 | //------------------ | ||||||
162 | // brun | ||||||
163 | //------------------ | ||||||
164 | jerror_t DTrackTimeBased_factory::brun(jana::JEventLoop *loop, int32_t runnumber) | ||||||
165 | { | ||||||
166 | // Get the geometry | ||||||
167 | DApplication* dapp=dynamic_cast<DApplication*>(loop->GetJApplication()); | ||||||
168 | geom = dapp->GetDGeometry(runnumber); | ||||||
169 | // Check for magnetic field | ||||||
170 | dIsNoFieldFlag = (dynamic_cast<const DMagneticFieldMapNoField*>(dapp->GetBfield(runnumber)) != NULL__null); | ||||||
| |||||||
171 | |||||||
172 | if(dIsNoFieldFlag
| ||||||
173 | //Setting this flag makes it so that JANA does not delete the objects in | ||||||
174 | //_data. This factory will manage this memory. | ||||||
175 | //This is all of these pointers are just copied from the "StraightLine" | ||||||
176 | //factory, and should not be re-deleted. | ||||||
177 | SetFactoryFlag(NOT_OBJECT_OWNER); | ||||||
178 | } | ||||||
179 | else{ | ||||||
180 | ClearFactoryFlag(NOT_OBJECT_OWNER); //This factory will create it's own obje | ||||||
181 | } | ||||||
182 | |||||||
183 | // Get pointer to TrackFitter object that actually fits a track | ||||||
184 | vector<const DTrackFitter *> fitters; | ||||||
185 | loop->Get(fitters); | ||||||
186 | if(fitters.size()<1){ | ||||||
187 | _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<187<<" "<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<<endl; | ||||||
188 | return RESOURCE_UNAVAILABLE; | ||||||
189 | } | ||||||
190 | |||||||
191 | // Drop the const qualifier from the DTrackFitter pointer (I'm surely going to hell for this!) | ||||||
192 | fitter = const_cast<DTrackFitter*>(fitters[0]); | ||||||
193 | |||||||
194 | // Warn user if something happened that caused us NOT to get a fitter object pointer | ||||||
195 | if(!fitter){ | ||||||
196 | _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<196<<" "<<"Unable to get a DTrackFitter object! NO Charged track fitting will be done!"<<endl; | ||||||
197 | return RESOURCE_UNAVAILABLE; | ||||||
198 | } | ||||||
199 | |||||||
200 | // Get the particle ID algorithms | ||||||
201 | vector<const DParticleID *> pid_algorithms; | ||||||
202 | loop->Get(pid_algorithms); | ||||||
203 | if(pid_algorithms.size()<1){ | ||||||
204 | _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<204<<" "<<"Unable to get a DParticleID object! NO PID will be done!"<<endl; | ||||||
205 | return RESOURCE_UNAVAILABLE; | ||||||
206 | } | ||||||
207 | |||||||
208 | pid_algorithm = pid_algorithms[0]; | ||||||
209 | |||||||
210 | // Warn user if something happened that caused us NOT to get a pid_algorithm object pointer | ||||||
211 | if(!pid_algorithm){ | ||||||
212 | _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<212<<" "<<"Unable to get a DParticleID object! NO PID will be done!"<<endl; | ||||||
213 | return RESOURCE_UNAVAILABLE; | ||||||
214 | } | ||||||
215 | |||||||
216 | |||||||
217 | if(DEBUG_HISTS){ | ||||||
218 | dapp->Lock(); | ||||||
219 | |||||||
220 | // Histograms may already exist. (Another thread may have created them) | ||||||
221 | // Try and get pointers to the existing ones. | ||||||
222 | fom_chi2_trk = (TH1F*)gROOT(ROOT::GetROOT())->FindObject("fom_chi2_trk"); | ||||||
223 | fom = (TH1F*)gROOT(ROOT::GetROOT())->FindObject("fom"); | ||||||
224 | hitMatchFOM = (TH1F*)gROOT(ROOT::GetROOT())->FindObject("hitMatchFOM"); | ||||||
225 | chi2_trk_mom = (TH2F*)gROOT(ROOT::GetROOT())->FindObject("chi2_trk_mom"); | ||||||
226 | |||||||
227 | if(!fom_chi2_trk)fom_chi2_trk = new TH1F("fom_chi2_trk","PID FOM: #chi^{2}/Ndf from tracking", 1000, 0.0, 100.0); | ||||||
228 | if(!fom)fom = new TH1F("fom","Combined PID FOM", 1000, 0.0, 1.01); | ||||||
229 | if(!hitMatchFOM)hitMatchFOM = new TH1F("hitMatchFOM","Total Fraction of Hit Matches", 101, 0.0, 1.01); | ||||||
230 | if(!chi2_trk_mom)chi2_trk_mom = new TH2F("chi2_trk_mom","Track #chi^{2}/Ndf versus Kinematic #chi^{2}/Ndf", 1000, 0.0, 100.0, 1000, 0.,100.); | ||||||
231 | |||||||
232 | |||||||
233 | Hstart_time=(TH2F*)gROOT(ROOT::GetROOT())->FindObject("Hstart_time"); | ||||||
234 | if (!Hstart_time) Hstart_time=new TH2F("Hstart_time", | ||||||
235 | "vertex time source vs. time", | ||||||
236 | 300,-50,50,9,-0.5,8.5); | ||||||
237 | |||||||
238 | dapp->Unlock(); | ||||||
239 | |||||||
240 | } | ||||||
241 | |||||||
242 | return NOERROR; | ||||||
243 | } | ||||||
244 | |||||||
245 | //------------------ | ||||||
246 | // evnt | ||||||
247 | //------------------ | ||||||
248 | jerror_t DTrackTimeBased_factory::evnt(JEventLoop *loop, uint64_t eventnumber) | ||||||
249 | { | ||||||
250 | // Save event number to help with debugging | ||||||
251 | myevt=eventnumber; | ||||||
252 | if(!fitter)return NOERROR; | ||||||
253 | |||||||
254 | if(dIsNoFieldFlag){ | ||||||
255 | //Clear previous objects: | ||||||
256 | //JANA doesn't do it because NOT_OBJECT_OWNER was set | ||||||
257 | //It DID delete them though, in the "StraightLine" factory | ||||||
258 | _data.clear(); | ||||||
259 | |||||||
260 | vector<const DTrackTimeBased*> locTimeBasedTracks; | ||||||
261 | loop->Get(locTimeBasedTracks, "StraightLine"); | ||||||
262 | for(size_t loc_i = 0; loc_i < locTimeBasedTracks.size(); ++loc_i) | ||||||
263 | _data.push_back(const_cast<DTrackTimeBased*>(locTimeBasedTracks[loc_i])); | ||||||
264 | return NOERROR; | ||||||
265 | } | ||||||
266 | |||||||
267 | // Get candidates and hits | ||||||
268 | vector<const DTrackWireBased*> tracks; | ||||||
269 | loop->Get(tracks); | ||||||
270 | if (tracks.size()==0) return NOERROR; | ||||||
271 | |||||||
272 | // get start counter hits | ||||||
273 | vector<const DSCHit*>sc_hits; | ||||||
274 | if (USE_SC_TIME){ | ||||||
275 | loop->Get(sc_hits); | ||||||
276 | } | ||||||
277 | |||||||
278 | // Get TOF points | ||||||
279 | vector<const DTOFPoint*> tof_points; | ||||||
280 | if (USE_TOF_TIME){ | ||||||
281 | loop->Get(tof_points); | ||||||
282 | } | ||||||
283 | |||||||
284 | // Get BCAL and FCAL showers | ||||||
285 | vector<const DBCALShower*>bcal_showers; | ||||||
286 | if (USE_BCAL_TIME){ | ||||||
287 | loop->Get(bcal_showers); | ||||||
288 | } | ||||||
289 | vector<const DFCALShower*>fcal_showers; | ||||||
290 | if (USE_FCAL_TIME){ | ||||||
291 | loop->Get(fcal_showers); | ||||||
292 | } | ||||||
293 | |||||||
294 | vector<const DMCThrown*> mcthrowns; | ||||||
295 | loop->Get(mcthrowns, "FinalState"); | ||||||
296 | |||||||
297 | // Loop over candidates | ||||||
298 | for(unsigned int i=0; i<tracks.size(); i++){ | ||||||
299 | const DTrackWireBased *track = tracks[i]; | ||||||
300 | |||||||
301 | unsigned int num=_data.size(); | ||||||
302 | |||||||
303 | // Create vector of start times from various sources | ||||||
304 | vector<DTrackTimeBased::DStartTime_t>start_times; | ||||||
305 | CreateStartTimeList(track,sc_hits,tof_points,bcal_showers,fcal_showers,start_times); | ||||||
306 | |||||||
307 | // Fit the track | ||||||
308 | DoFit(track,start_times,loop,track->mass()); | ||||||
309 | |||||||
310 | //_DBG_<< "eventnumber: " << eventnumber << endl; | ||||||
311 | if (PID_FORCE_TRUTH && _data.size()>num) { | ||||||
312 | // Add figure-of-merit based on difference between thrown and reconstructed momentum | ||||||
313 | // if more than half of the track's hits match MC truth hits and also (charge,mass) | ||||||
314 | // match; add FOM=0 otherwise | ||||||
315 | _data[_data.size()-1]->FOM=GetTruthMatchingFOM(i,_data[_data.size()-1], | ||||||
316 | mcthrowns); | ||||||
317 | } | ||||||
318 | } // loop over track candidates | ||||||
319 | |||||||
320 | // Filter out duplicate tracks | ||||||
321 | FilterDuplicates(); | ||||||
322 | |||||||
323 | // Fill in track data for missing hypotheses | ||||||
324 | if (INSERT_MISSING_HYPOTHESES){ | ||||||
325 | InsertMissingHypotheses(loop); | ||||||
326 | } | ||||||
327 | |||||||
328 | // Set MC Hit-matching information | ||||||
329 | for(size_t loc_i = 0; loc_i < _data.size(); ++loc_i) | ||||||
330 | { | ||||||
331 | if(!mcthrowns.empty()) | ||||||
332 | { | ||||||
333 | double hitFraction; | ||||||
334 | int thrownIndex = GetThrownIndex(mcthrowns, (DKinematicData*)_data[loc_i], hitFraction); | ||||||
335 | _data[loc_i]->dMCThrownMatchMyID = thrownIndex; | ||||||
336 | _data[loc_i]->dNumHitsMatchedToThrown = int(hitFraction * float(Get_NumTrackHits(_data[loc_i])) + 0.01); // + 0.01 so that it rounds down properly | ||||||
337 | } | ||||||
338 | else | ||||||
339 | { | ||||||
340 | _data[loc_i]->dMCThrownMatchMyID = -1; | ||||||
341 | _data[loc_i]->dNumHitsMatchedToThrown = 0; | ||||||
342 | } | ||||||
343 | } | ||||||
344 | |||||||
345 | return NOERROR; | ||||||
346 | } | ||||||
347 | |||||||
348 | //------------------ | ||||||
349 | // erun | ||||||
350 | //------------------ | ||||||
351 | jerror_t DTrackTimeBased_factory::erun(void) | ||||||
352 | { | ||||||
353 | return NOERROR; | ||||||
354 | } | ||||||
355 | |||||||
356 | //------------------ | ||||||
357 | // fini | ||||||
358 | //------------------ | ||||||
359 | jerror_t DTrackTimeBased_factory::fini(void) | ||||||
360 | { | ||||||
361 | return NOERROR; | ||||||
362 | } | ||||||
363 | |||||||
364 | //------------------ | ||||||
365 | // FilterDuplicates | ||||||
366 | //------------------ | ||||||
367 | void DTrackTimeBased_factory::FilterDuplicates(void) | ||||||
368 | { | ||||||
369 | /// Look through all current DTrackTimeBased objects and remove any | ||||||
370 | /// that have most of their hits in common with another track | ||||||
371 | |||||||
372 | if(_data.size()==0)return; | ||||||
373 | |||||||
374 | if(DEBUG_LEVEL>2)_DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<374<<" "<<"Looking for clones of time-based tracks ..."<<endl; | ||||||
375 | // We want to remove duplicate tracks corresponding to actual particles, | ||||||
376 | // not just duplicate fitted tracks for certain mass hypotheses -- this | ||||||
377 | // is partly because at a later stage the holes in the list of mass | ||||||
378 | // hypotheses are filled in, thereby spoiling the whole point of this | ||||||
379 | // part of the code! | ||||||
380 | // Keep track of pairs of candididate id's, one for which we want to | ||||||
381 | // keep all the results of fitting with different mass hypotheses, | ||||||
382 | // the other for which we want to delete all the results of fitting. | ||||||
383 | // We need both vectors to take into account potential ambiguities: | ||||||
384 | // for one mass hypothesis starting with one candidate may be "better" | ||||||
385 | // than starting with a second clone candidate, whereas for a second | ||||||
386 | // mass hypothesis, the opposite may be true. | ||||||
387 | vector<unsigned int> candidates_to_keep; | ||||||
388 | vector<unsigned int> candidates_to_delete; | ||||||
389 | for(unsigned int i=0; i<_data.size()-1; i++){ | ||||||
390 | DTrackTimeBased *dtrack1 = _data[i]; | ||||||
391 | |||||||
392 | vector<const DCDCTrackHit*> cdchits1; | ||||||
393 | vector<const DFDCPseudo*> fdchits1; | ||||||
394 | dtrack1->Get(cdchits1); | ||||||
395 | dtrack1->Get(fdchits1); | ||||||
396 | // Total number of hits in this candidate | ||||||
397 | unsigned int num_cdc1=cdchits1.size(); | ||||||
398 | unsigned int num_fdc1=fdchits1.size(); | ||||||
399 | unsigned int total1 = num_cdc1+num_fdc1; | ||||||
400 | |||||||
401 | JObject::oid_t cand1=dtrack1->candidateid; | ||||||
402 | for(unsigned int j=i+1; j<_data.size(); j++){ | ||||||
403 | DTrackTimeBased *dtrack2 = _data[j]; | ||||||
404 | if (dtrack2->candidateid==cand1) continue; | ||||||
405 | |||||||
406 | vector<const DCDCTrackHit*> cdchits2; | ||||||
407 | vector<const DFDCPseudo*> fdchits2; | ||||||
408 | dtrack2->Get(cdchits2); | ||||||
409 | dtrack2->Get(fdchits2); | ||||||
410 | |||||||
411 | // Total number of hits in this candidate | ||||||
412 | unsigned int num_cdc2=cdchits2.size(); | ||||||
413 | unsigned int num_fdc2=fdchits2.size(); | ||||||
414 | unsigned int total2 = num_cdc2+num_fdc2; | ||||||
415 | |||||||
416 | // Count number of cdc and fdc hits in common | ||||||
417 | unsigned int Ncdc = count_common_members(cdchits1, cdchits2); | ||||||
418 | unsigned int Nfdc = count_common_members(fdchits1, fdchits2); | ||||||
419 | |||||||
420 | if(DEBUG_LEVEL>3){ | ||||||
421 | _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<421<<" "<<"cand1:"<<cand1<<" cand2:"<<dtrack2->candidateid<<endl; | ||||||
422 | _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<422<<" "<<" Ncdc="<<Ncdc<<" num_cdc1="<<num_cdc1<<" num_cdc2="<<num_cdc2<<endl; | ||||||
423 | _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<423<<" "<<" Nfdc="<<Nfdc<<" num_fdc1="<<num_fdc1<<" num_fdc2="<<num_fdc2<<endl; | ||||||
424 | } | ||||||
425 | unsigned int total = Ncdc + Nfdc; | ||||||
426 | // If the tracks share at most one hit, consider them | ||||||
427 | // to be separate tracks | ||||||
428 | if (total<=1) continue; | ||||||
429 | |||||||
430 | // Deal with the case where there are cdc hits in | ||||||
431 | // common between the tracks but there were no fdc | ||||||
432 | // hits used in one of the tracks. | ||||||
433 | if (Ncdc>0 && (num_fdc1>0 || num_fdc2>0) | ||||||
434 | && (num_fdc1*num_fdc2)==0) continue; | ||||||
435 | |||||||
436 | // Deal with the case where there are fdc hits in | ||||||
437 | // common between the tracks but no cdc hits used in | ||||||
438 | // one of the tracks. | ||||||
439 | if (Nfdc>0 && (num_cdc1>0 || num_cdc2>0) | ||||||
440 | && (num_cdc1*num_cdc2)==0) continue; | ||||||
441 | |||||||
442 | // Look for tracks with many common hits in the CDC | ||||||
443 | if (num_cdc1>0 && num_cdc2>0){ | ||||||
444 | if (double(Ncdc)/double(num_cdc1)<0.9) continue; | ||||||
445 | if (double(Ncdc)/double(num_cdc2)<0.9) continue; | ||||||
446 | } | ||||||
447 | // Look for tracks with many common hits in the FDC | ||||||
448 | if (num_fdc1>0 && num_fdc2>0){ | ||||||
449 | if (double(Nfdc)/double(num_fdc1)<0.9) continue; | ||||||
450 | if (double(Nfdc)/double(num_fdc2)<0.9) continue; | ||||||
451 | } | ||||||
452 | |||||||
453 | if(total1<total2){ | ||||||
454 | candidates_to_delete.push_back(cand1); | ||||||
455 | candidates_to_keep.push_back(dtrack2->candidateid); | ||||||
456 | }else if(total2<total1){ | ||||||
457 | candidates_to_delete.push_back(dtrack2->candidateid); | ||||||
458 | candidates_to_keep.push_back(cand1); | ||||||
459 | }else if(dtrack1->FOM > dtrack2->FOM){ | ||||||
460 | candidates_to_delete.push_back(dtrack2->candidateid); | ||||||
461 | candidates_to_keep.push_back(cand1); | ||||||
462 | }else{ | ||||||
463 | candidates_to_delete.push_back(cand1); | ||||||
464 | candidates_to_keep.push_back(dtrack2->candidateid); | ||||||
465 | } | ||||||
466 | } | ||||||
467 | } | ||||||
468 | |||||||
469 | if(DEBUG_LEVEL>2)_DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<469<<" "<<"Found "<<candidates_to_delete.size()<<" time-based clones"<<endl; | ||||||
470 | |||||||
471 | |||||||
472 | // Return now if we're keeping everyone | ||||||
473 | if(candidates_to_delete.size()==0)return; | ||||||
474 | |||||||
475 | // Deal with the ambiguity problem mentioned above | ||||||
476 | for (unsigned int i=0;i<candidates_to_keep.size();i++){ | ||||||
477 | for (unsigned int j=0;j<candidates_to_delete.size();j++){ | ||||||
478 | if (candidates_to_keep[i]==candidates_to_delete[j]){ | ||||||
479 | candidates_to_delete.erase(candidates_to_delete.begin()+j); | ||||||
480 | break; | ||||||
481 | } | ||||||
482 | } | ||||||
483 | |||||||
484 | } | ||||||
485 | |||||||
486 | // Copy pointers that we want to keep to a new container and delete | ||||||
487 | // the clone objects | ||||||
488 | vector<DTrackTimeBased*> new_data; | ||||||
489 | sort(_data.begin(),_data.end(),DTrackTimeBased_cmp); | ||||||
490 | for (unsigned int i=0;i<_data.size();i++){ | ||||||
491 | bool keep_track=true; | ||||||
492 | for (unsigned int j=0;j<candidates_to_delete.size();j++){ | ||||||
493 | if (_data[i]->candidateid==candidates_to_delete[j]){ | ||||||
494 | keep_track=false; | ||||||
495 | if(DEBUG_LEVEL>1){ | ||||||
496 | _DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<496<<" "<<"Deleting clone time-based fitted result "<<i | ||||||
497 | << " in event " << myevt << endl; | ||||||
498 | } | ||||||
499 | break; | ||||||
500 | } | ||||||
501 | } | ||||||
502 | if (keep_track){ | ||||||
503 | new_data.push_back(_data[i]); | ||||||
504 | } | ||||||
505 | else delete _data[i]; | ||||||
506 | } | ||||||
507 | _data = new_data; | ||||||
508 | } | ||||||
509 | |||||||
510 | // Returns a FOM based on difference between thrown and reconstructed momentum if track matches MC truth information, | ||||||
511 | // returns a FOM=0 otherwise; | ||||||
512 | // a match requires identical masses and charges, and that more than half of the track's hits match the truth hits | ||||||
513 | double DTrackTimeBased_factory::GetTruthMatchingFOM(int trackIndex,DTrackTimeBased *track,vector<const DMCThrown*>mcthrowns) { | ||||||
514 | bool match=false; | ||||||
515 | |||||||
516 | DLorentzVector fourMom = track->lorentzMomentum(); | ||||||
517 | //DLorentzVector gen_fourMom[mcthrowns.size()]; | ||||||
518 | vector<DLorentzVector> gen_fourMom(mcthrowns.size()); | ||||||
519 | for(unsigned int i=0; i<mcthrowns.size(); i++){ | ||||||
520 | gen_fourMom[i] = mcthrowns[i]->lorentzMomentum(); | ||||||
521 | } | ||||||
522 | |||||||
523 | // Get info for thrown track | ||||||
524 | double f = 0.; | ||||||
525 | int thrownIndex = GetThrownIndex(mcthrowns, track, f); | ||||||
526 | if(thrownIndex<=0 || f<=0.5) return 0.; | ||||||
527 | |||||||
528 | double delta_pt_over_pt = (fourMom.Pt()-gen_fourMom[thrownIndex-1].Pt())/gen_fourMom[thrownIndex-1].Pt(); | ||||||
529 | double delta_theta = (fourMom.Theta()-gen_fourMom[thrownIndex-1].Theta())*1000.0; // in milliradians | ||||||
530 | double delta_phi = (fourMom.Phi()-gen_fourMom[thrownIndex-1].Phi())*1000.0; // in milliradians | ||||||
531 | double chisq = pow(delta_pt_over_pt/0.04, 2.0) + pow(delta_theta/20.0, 2.0) + pow(delta_phi/20.0, 2.0); | ||||||
532 | |||||||
533 | if (fabs(track->mass()-mcthrowns[thrownIndex-1]->mass())<0.01 && track->charge()==mcthrowns[thrownIndex-1]->charge()) | ||||||
534 | match = true; | ||||||
535 | |||||||
536 | double trk_chi2=track->chisq; | ||||||
537 | unsigned int ndof=track->Ndof; | ||||||
538 | |||||||
539 | if(DEBUG_HISTS&&match){ | ||||||
540 | fom_chi2_trk->Fill(track->chisq); | ||||||
541 | chi2_trk_mom->Fill(chisq/3.,trk_chi2/ndof); | ||||||
542 | fom->Fill(TMath::Prob(chisq,3)); | ||||||
543 | } | ||||||
544 | |||||||
545 | /*_DBG_ << "f: " << f << endl; | ||||||
546 | _DBG_ << "trk_chi2: " << trk_chi2 << endl; | ||||||
547 | _DBG_ << "ndof: " << ndof << endl; | ||||||
548 | _DBG_ << "throwncharge: " << mcthrowns[thrownIndex-1]->charge() << endl; | ||||||
549 | _DBG_ << "trackcharge: " << track->charge() << endl; | ||||||
550 | _DBG_ << "chargediff: " << fabs(track->charge()-mcthrowns[thrownIndex-1]->charge()) << endl; | ||||||
551 | _DBG_ << "thrownmass: " << mcthrowns[thrownIndex-1]->mass() << endl; | ||||||
552 | _DBG_ << "trackmass: " << track->mass() << endl; | ||||||
553 | _DBG_ << "massdiff: " << fabs(track->mass()-mcthrowns[thrownIndex-1]->mass()) << endl; | ||||||
554 | _DBG_ << "chisq: " << chisq << endl; | ||||||
555 | _DBG_ << "match?: " << match << endl; | ||||||
556 | _DBG_ << "thrownIndex: " << thrownIndex << " trackIndex: " << trackIndex << endl; | ||||||
557 | _DBG_<< "track " << setprecision(4) << "Px: " << fourMom.Px() << " Py: " << fourMom.Py() << " Pz: " << fourMom.Pz() << " E: " << fourMom.E() << " M: " << fourMom.M() << " pt: " << fourMom.Pt() << " theta: " << fourMom.Theta() << " phi: " << fourMom.Phi() << endl; | ||||||
558 | _DBG_<< "thrown " << setprecision(4) << "Px: " << gen_fourMom[thrownIndex-1].Px() << " Py: " << gen_fourMom[thrownIndex-1].Py() << " Pz: " << gen_fourMom[thrownIndex-1].Pz() << " E: " << gen_fourMom[thrownIndex-1].E() << " M: " << gen_fourMom[thrownIndex-1].M() << " pt: " << gen_fourMom[thrownIndex-1].Pt() << " theta: " << gen_fourMom[thrownIndex-1].Theta() << " phi: " << gen_fourMom[thrownIndex-1].Phi() << endl;*/ | ||||||
559 | |||||||
560 | return (match) ? TMath::Prob(chisq,3) : 0.0; | ||||||
561 | } | ||||||
562 | |||||||
563 | //------------------ | ||||||
564 | // GetThrownIndex | ||||||
565 | //------------------ | ||||||
566 | int DTrackTimeBased_factory::GetThrownIndex(vector<const DMCThrown*>& locMCThrowns, const DKinematicData *kd, double &f) | ||||||
567 | { | ||||||
568 | // The DKinematicData object should be a DTrackCandidate, DTrackWireBased, or DParticle which | ||||||
569 | // has associated objects for the hits | ||||||
570 | vector<const DCDCTrackHit*> cdctrackhits; | ||||||
571 | kd->Get(cdctrackhits); | ||||||
572 | vector<const DFDCPseudo*> fdcpseudos; | ||||||
573 | kd->Get(fdcpseudos); | ||||||
574 | |||||||
575 | int locTotalNumHits = cdctrackhits.size() + fdcpseudos.size(); | ||||||
576 | if(locTotalNumHits == 0) | ||||||
577 | { | ||||||
578 | f = 0; | ||||||
579 | return -1; | ||||||
580 | } | ||||||
581 | |||||||
582 | // The track number is buried in the truth hit objects of type DMCTrackHit. These should be | ||||||
583 | // associated objects for the individual hit objects. We need to loop through them and | ||||||
584 | // keep track of how many hits for each track number we find | ||||||
585 | |||||||
586 | map<int, int> locHitMatches; //first int is MC my id, second is num hits | ||||||
587 | for(size_t loc_i = 0; loc_i < locMCThrowns.size(); ++loc_i) | ||||||
588 | { | ||||||
589 | if(fabs(locMCThrowns[loc_i]->charge()) > 0.9) | ||||||
590 | locHitMatches[locMCThrowns[loc_i]->myid] = 0; | ||||||
591 | } | ||||||
592 | |||||||
593 | // CDC hits | ||||||
594 | for(size_t loc_i = 0; loc_i < cdctrackhits.size(); ++loc_i) | ||||||
595 | { | ||||||
596 | const DCDCHit* locCDCHit = NULL__null; | ||||||
597 | cdctrackhits[loc_i]->GetSingle(locCDCHit); | ||||||
598 | vector<const DCDCHit*> locTruthCDCHits; | ||||||
599 | locCDCHit->Get(locTruthCDCHits); | ||||||
600 | if(locTruthCDCHits.empty()) continue; | ||||||
601 | |||||||
602 | int itrack = locTruthCDCHits[0]->itrack; | ||||||
603 | if(locHitMatches.find(itrack) == locHitMatches.end()) | ||||||
604 | continue; | ||||||
605 | ++locHitMatches[itrack]; | ||||||
606 | } | ||||||
607 | |||||||
608 | // FDC hits | ||||||
609 | for(size_t loc_i = 0; loc_i < fdcpseudos.size(); ++loc_i) | ||||||
610 | { | ||||||
611 | vector<const DMCTrackHit*> mctrackhits; | ||||||
612 | fdcpseudos[loc_i]->Get(mctrackhits); | ||||||
613 | if(mctrackhits.empty()) | ||||||
614 | continue; | ||||||
615 | if(!mctrackhits[0]->primary) | ||||||
616 | continue; | ||||||
617 | |||||||
618 | int itrack = mctrackhits[0]->itrack; | ||||||
619 | if(locHitMatches.find(itrack) == locHitMatches.end()) | ||||||
620 | continue; | ||||||
621 | ++locHitMatches[itrack]; | ||||||
622 | } | ||||||
623 | |||||||
624 | // Find DMCThrown::myid with most wires hit | ||||||
625 | map<int, int>::iterator locIterator = locHitMatches.begin(); | ||||||
626 | int locBestMyID = -1; | ||||||
627 | int locBestNumHits = 0; | ||||||
628 | for(; locIterator != locHitMatches.end(); ++locIterator) | ||||||
629 | { | ||||||
630 | if(locIterator->second <= locBestNumHits) | ||||||
631 | continue; | ||||||
632 | locBestNumHits = locIterator->second; | ||||||
633 | locBestMyID = locIterator->first; | ||||||
634 | } | ||||||
635 | |||||||
636 | // total fraction of reconstructed hits that match truth hits | ||||||
637 | f = 1.0*locBestNumHits/locTotalNumHits; | ||||||
638 | if(DEBUG_HISTS)hitMatchFOM->Fill(f); | ||||||
639 | |||||||
640 | return locBestMyID; | ||||||
641 | } | ||||||
642 | |||||||
643 | |||||||
644 | // Create a list of start (vertex) times from various sources, ordered by | ||||||
645 | // uncertainty. | ||||||
646 | void DTrackTimeBased_factory | ||||||
647 | ::CreateStartTimeList(const DTrackWireBased *track, | ||||||
648 | vector<const DSCHit*>&sc_hits, | ||||||
649 | vector<const DTOFPoint*>&tof_points, | ||||||
650 | vector<const DBCALShower*>&bcal_showers, | ||||||
651 | vector<const DFCALShower*>&fcal_showers, | ||||||
652 | vector<DTrackTimeBased::DStartTime_t>&start_times){ | ||||||
653 | DTrackTimeBased::DStartTime_t start_time; | ||||||
654 | |||||||
655 | // Match to the start counter and the outer detectors | ||||||
656 | double locStartTimeVariance = 0.0; | ||||||
657 | double track_t0=track->t0(); | ||||||
658 | double locStartTime = track_t0; // initial guess from tracking | ||||||
659 | |||||||
660 | // Get start time estimate from Start Counter | ||||||
661 | if (pid_algorithm->Get_StartTime(track->extrapolations.at(SYS_START),sc_hits,locStartTime)){ | ||||||
662 | start_time.t0=locStartTime; | ||||||
663 | // start_time.t0_sigma=sqrt(locTimeVariance); //uncomment when ready | ||||||
664 | start_time.t0_sigma=sqrt(locStartTimeVariance); | ||||||
665 | start_time.system=SYS_START; | ||||||
666 | start_times.push_back(start_time); | ||||||
667 | } | ||||||
668 | // Get start time estimate from TOF | ||||||
669 | locStartTime = track_t0; // initial guess from tracking | ||||||
670 | if (pid_algorithm->Get_StartTime(track->extrapolations.at(SYS_TOF),tof_points,locStartTime)){ | ||||||
671 | // Fill in the start time vector | ||||||
672 | start_time.t0=locStartTime; | ||||||
673 | start_time.t0_sigma=sqrt(locStartTimeVariance); | ||||||
674 | // start_time.t0_sigma=sqrt(locTimeVariance); //uncomment when ready | ||||||
675 | start_time.system=SYS_TOF; | ||||||
676 | start_times.push_back(start_time); | ||||||
677 | } | ||||||
678 | // Get start time estimate from FCAL | ||||||
679 | locStartTime = track_t0; // initial guess from tracking | ||||||
680 | if (pid_algorithm->Get_StartTime(track->extrapolations.at(SYS_FCAL),fcal_showers,locStartTime)){ | ||||||
681 | // Fill in the start time vector | ||||||
682 | start_time.t0=locStartTime; | ||||||
683 | start_time.t0_sigma=sqrt(locStartTimeVariance); | ||||||
684 | // start_time.t0_sigma=sqrt(locTimeVariance); //uncomment when ready | ||||||
685 | start_time.system=SYS_FCAL; | ||||||
686 | start_times.push_back(start_time); | ||||||
687 | } | ||||||
688 | // Get start time estimate from BCAL | ||||||
689 | locStartTime=track_t0; | ||||||
690 | if (pid_algorithm->Get_StartTime(track->extrapolations.at(SYS_BCAL),bcal_showers,locStartTime)){ | ||||||
691 | // Fill in the start time vector | ||||||
692 | start_time.t0=locStartTime; | ||||||
693 | start_time.t0_sigma=0.5; | ||||||
694 | // start_time.t0_sigma=sqrt(locTimeVariance); //uncomment when ready | ||||||
695 | start_time.system=SYS_BCAL; | ||||||
696 | start_times.push_back(start_time); | ||||||
697 | } | ||||||
698 | // Add the t0 estimate from the tracking | ||||||
699 | start_time.t0=track_t0; | ||||||
700 | start_time.t0_sigma=5.; | ||||||
701 | start_time.system=track->t0_detector(); | ||||||
702 | start_times.push_back(start_time); | ||||||
703 | |||||||
704 | // Set t0 for the fit to the first entry in the list. Usually this will be | ||||||
705 | // from the start counter. | ||||||
706 | mStartTime=start_times[0].t0; | ||||||
707 | mStartDetector=start_times[0].system; | ||||||
708 | |||||||
709 | // _DBG_ << mStartDetector << " " << mStartTime << endl; | ||||||
710 | |||||||
711 | } | ||||||
712 | |||||||
713 | // Create a list of start times and do the fit for a particular mass hypothesis | ||||||
714 | bool DTrackTimeBased_factory::DoFit(const DTrackWireBased *track, | ||||||
715 | vector<DTrackTimeBased::DStartTime_t>&start_times, | ||||||
716 | JEventLoop *loop, | ||||||
717 | double mass){ | ||||||
718 | if(DEBUG_LEVEL>1){_DBG__std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<718<<std::endl;_DBG_std::cerr<<"libraries/TRACKING/DTrackTimeBased_factory.cc" <<":"<<718<<" "<<"---- Starting time based fit with mass: "<<mass<<endl;} | ||||||
719 | // Get the hits from the wire-based track | ||||||
720 | vector<const DFDCPseudo*>myfdchits; | ||||||
721 | track->GetT(myfdchits); | ||||||
722 | vector<const DCDCTrackHit *>mycdchits; | ||||||
723 | track->GetT(mycdchits); | ||||||
724 | |||||||
725 | // Do the fit | ||||||
726 | DTrackFitter::fit_status_t status = DTrackFitter::kFitNotDone; | ||||||
727 | if (USE_HITS_FROM_WIREBASED_FIT) { | ||||||
728 | fitter->Reset(); | ||||||
729 | fitter->SetFitType(DTrackFitter::kTimeBased); | ||||||
730 | |||||||
731 | fitter->AddHits(myfdchits); | ||||||
732 | fitter->AddHits(mycdchits); | ||||||
733 | |||||||
734 | status=fitter->FitTrack(track->position(),track->momentum(), | ||||||
735 | track->charge(),mass,mStartTime,mStartDetector); | ||||||
736 | } | ||||||
737 | else{ | ||||||
738 | fitter->Reset(); | ||||||
739 | fitter->SetFitType(DTrackFitter::kTimeBased); | ||||||
740 | status = fitter->FindHitsAndFitTrack(*track, track->extrapolations,loop, | ||||||
741 | mass, | ||||||
742 | mycdchits.size()+2*myfdchits.size(), | ||||||
743 | mStartTime,mStartDetector); | ||||||
744 | |||||||
745 | // If the status is kFitNotDone, then not enough hits were attached to this | ||||||
746 | // track using the hit-gathering algorithm. In this case get the hits | ||||||
747 | // from the wire-based track | ||||||
748 | if (status==DTrackFitter::kFitNotDone){ | ||||||
749 | //_DBG_ << " Using wire-based hits " << endl; | ||||||
750 | fitter->Reset(); | ||||||
751 | fitter->SetFitType(DTrackFitter::kTimeBased); | ||||||
752 | fitter->AddHits(myfdchits); | ||||||
753 | fitter->AddHits(mycdchits); | ||||||
754 | |||||||
755 | status=fitter->FitTrack(track->position(),track->momentum(), | ||||||
756 | track->charge(),mass,mStartTime,mStartDetector); | ||||||
757 | } | ||||||
758 | |||||||
759 | } | ||||||
760 | |||||||
761 | // if the fit returns chisq=-1, something went terribly wrong. We may still | ||||||
762 | // have a usable track from the wire-based pass. In this case set | ||||||
763 | // kFitNoImprovement so we can save the wire-based results. | ||||||
764 | if (fitter->GetChisq()<0){ | ||||||
765 | status=DTrackFitter::kFitNoImprovement; | ||||||
766 | } | ||||||
767 | |||||||
768 | // In the transition region between the CDC and the FDC where the track | ||||||
769 | // contains both CDC and FDC hits, sometimes too many hits are discarded in | ||||||
770 | // the time-based phase and the time-based fit result does not improve on the | ||||||
771 | // wire-based fit result. In this case set the status word to | ||||||
772 | // kFitNoImprovement and copy the wire-based parameters into the time-based | ||||||
773 | // class. | ||||||
774 | if (myfdchits.size()>3 && mycdchits.size()>3){ | ||||||
775 | unsigned int ndof=fitter->GetNdof(); | ||||||
776 | if (TMath::Prob(track->chisq,track->Ndof)> | ||||||
777 | TMath::Prob(fitter->GetChisq(),ndof)&&ndof<5) | ||||||
778 | status=DTrackFitter::kFitNoImprovement; | ||||||
779 | } | ||||||
780 | |||||||
781 | // Check the status value from the fit | ||||||
782 | switch(status){ | ||||||
783 | case DTrackFitter::kFitNotDone: | ||||||
784 | //_DBG_<<"Fitter returned kFitNotDone. This should never happen!!"<<endl; | ||||||
785 | case DTrackFitter::kFitFailed: | ||||||
786 | break; | ||||||
787 | case DTrackFitter::kFitNoImprovement: | ||||||
788 | { | ||||||
789 | // Create a new time-based track object | ||||||
790 | DTrackTimeBased *timebased_track = new DTrackTimeBased(); | ||||||
791 | *static_cast<DTrackingData*>(timebased_track) = *static_cast<const DTrackingData*>(track); | ||||||
792 | |||||||
793 | timebased_track->chisq = track->chisq; | ||||||
794 | timebased_track->Ndof = track->Ndof; | ||||||
795 | timebased_track->pulls = track->pulls; | ||||||
796 | timebased_track->extrapolations = track->extrapolations; | ||||||
797 | timebased_track->trackid = track->id; | ||||||
798 | timebased_track->candidateid=track->candidateid; | ||||||
799 | timebased_track->FOM=track->FOM; | ||||||
800 | timebased_track->flags=DTrackTimeBased::FLAG__USED_WIREBASED_FIT; | ||||||
801 | |||||||
802 | // add the list of start times | ||||||
803 | timebased_track->start_times.assign(start_times.begin(), | ||||||
804 | start_times.end()); | ||||||
805 | |||||||
806 | for(unsigned int m=0; m<myfdchits.size(); m++) | ||||||
807 | timebased_track->AddAssociatedObject(myfdchits[m]); | ||||||
808 | for(unsigned int m=0; m<mycdchits.size(); m++) | ||||||
809 | timebased_track->AddAssociatedObject(mycdchits[m]); | ||||||
810 | |||||||
811 | timebased_track->measured_cdc_hits_on_track = mycdchits.size(); | ||||||
812 | timebased_track->measured_fdc_hits_on_track = myfdchits.size(); | ||||||
813 | |||||||
814 | // dEdx | ||||||
815 | double locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp; | ||||||
816 | double locdx_CDC_amp,locdx_CDC; | ||||||
817 | unsigned int locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC; | ||||||
818 | pid_algorithm->CalcDCdEdx(timebased_track, locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp, locdx_CDC, locdx_CDC_amp,locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC); | ||||||
819 | |||||||
820 | timebased_track->ddEdx_FDC = locdEdx_FDC; | ||||||
821 | timebased_track->ddx_FDC = locdx_FDC; | ||||||
822 | timebased_track->dNumHitsUsedFordEdx_FDC = locNumHitsUsedFordEdx_FDC; | ||||||
823 | timebased_track->ddEdx_CDC = locdEdx_CDC; | ||||||
824 | timebased_track->ddEdx_CDC_amp = locdEdx_CDC_amp; | ||||||
825 | timebased_track->ddx_CDC = locdx_CDC; | ||||||
826 | timebased_track->ddx_CDC_amp = locdx_CDC_amp; | ||||||
827 | timebased_track->dNumHitsUsedFordEdx_CDC = locNumHitsUsedFordEdx_CDC; | ||||||
828 | |||||||
829 | timebased_track->potential_cdc_hits_on_track = fitter->GetNumPotentialCDCHits(); | ||||||
830 | timebased_track->potential_fdc_hits_on_track = fitter->GetNumPotentialFDCHits(); | ||||||
831 | |||||||
832 | timebased_track->AddAssociatedObject(track); | ||||||
833 | _data.push_back(timebased_track); | ||||||
834 | |||||||
835 | return true; | ||||||
836 | break; | ||||||
837 | } | ||||||
838 | case DTrackFitter::kFitSuccess: | ||||||
839 | { | ||||||
840 | // Create a new time-based track object | ||||||
841 | DTrackTimeBased *timebased_track = new DTrackTimeBased(); | ||||||
842 | *static_cast<DTrackingData*>(timebased_track) = fitter->GetFitParameters(); | ||||||
843 | |||||||
844 | timebased_track->setTime(mStartTime); | ||||||
845 | timebased_track->chisq = fitter->GetChisq(); | ||||||
846 | timebased_track->Ndof = fitter->GetNdof(); | ||||||
847 | timebased_track->pulls = std::move(fitter->GetPulls()); | ||||||
848 | timebased_track->extrapolations=std::move(fitter->GetExtrapolations()); | ||||||
849 | timebased_track->IsSmoothed = fitter->GetIsSmoothed(); | ||||||
850 | timebased_track->trackid = track->id; | ||||||
851 | timebased_track->candidateid=track->candidateid; | ||||||
852 | timebased_track->flags=DTrackTimeBased::FLAG__GOODFIT; | ||||||
853 | |||||||
854 | // Set the start time and add the list of start times | ||||||
855 | timebased_track->setT0(mStartTime,start_times[0].t0_sigma, mStartDetector); | ||||||
856 | timebased_track->start_times.assign(start_times.begin(), start_times.end()); | ||||||
857 | |||||||
858 | if (DEBUG_HISTS){ | ||||||
859 | int id=0; | ||||||
860 | if (mStartDetector==SYS_CDC) id=1; | ||||||
861 | else if (mStartDetector==SYS_FDC) id=2; | ||||||
862 | else if (mStartDetector==SYS_BCAL) id=3; | ||||||
863 | else if (mStartDetector==SYS_FCAL) id=4; | ||||||
864 | else if (mStartDetector==SYS_TOF) id=5; | ||||||
865 | |||||||
866 | Hstart_time->Fill(start_times[0].t0,id); | ||||||
867 | } | ||||||
868 | |||||||
869 | |||||||
870 | // Add hits used as associated objects | ||||||
871 | const vector<const DCDCTrackHit*> &cdchits = fitter->GetCDCFitHits(); | ||||||
872 | const vector<const DFDCPseudo*> &fdchits = fitter->GetFDCFitHits(); | ||||||
873 | |||||||
874 | unsigned int num_fdc_potential=fitter->GetNumPotentialFDCHits(); | ||||||
875 | unsigned int num_cdc_potential=fitter->GetNumPotentialCDCHits(); | ||||||
876 | |||||||
877 | DTrackTimeBased::hit_usage_t temp; | ||||||
878 | temp.inner_layer=0; | ||||||
879 | temp.outer_layer=0; | ||||||
880 | temp.total_hits=num_cdc_potential; | ||||||
881 | if (cdchits.size()>0){ | ||||||
882 | temp.inner_layer=cdchits[0]->wire->ring; | ||||||
883 | temp.outer_layer=cdchits[cdchits.size()-1]->wire->ring; | ||||||
884 | } | ||||||
885 | timebased_track->cdc_hit_usage=temp; | ||||||
886 | |||||||
887 | // Reset the structure | ||||||
888 | temp.inner_layer=0; | ||||||
889 | temp.outer_layer=0; | ||||||
890 | temp.total_hits=num_fdc_potential; | ||||||
891 | if (fdchits.size()>0){ | ||||||
892 | temp.inner_layer=fdchits[0]->wire->layer; | ||||||
893 | temp.outer_layer=fdchits[fdchits.size()-1]->wire->layer; | ||||||
894 | } | ||||||
895 | timebased_track->fdc_hit_usage=temp; | ||||||
896 | |||||||
897 | for(unsigned int m=0; m<cdchits.size(); m++) | ||||||
898 | timebased_track->AddAssociatedObject(cdchits[m]); | ||||||
899 | for(unsigned int m=0; m<fdchits.size(); m++) | ||||||
900 | timebased_track->AddAssociatedObject(fdchits[m]); | ||||||
901 | |||||||
902 | timebased_track->measured_cdc_hits_on_track = cdchits.size(); | ||||||
903 | timebased_track->measured_fdc_hits_on_track = fdchits.size(); | ||||||
904 | |||||||
905 | // dEdx | ||||||
906 | double locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp; | ||||||
907 | double locdx_CDC,locdx_CDC_amp; | ||||||
908 | unsigned int locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC; | ||||||
909 | pid_algorithm->CalcDCdEdx(timebased_track, locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp,locdx_CDC,locdx_CDC_amp, locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC); | ||||||
910 | |||||||
911 | timebased_track->ddEdx_FDC = locdEdx_FDC; | ||||||
912 | timebased_track->ddx_FDC = locdx_FDC; | ||||||
913 | timebased_track->dNumHitsUsedFordEdx_FDC = locNumHitsUsedFordEdx_FDC; | ||||||
914 | timebased_track->ddEdx_CDC = locdEdx_CDC; | ||||||
915 | timebased_track->ddEdx_CDC_amp= locdEdx_CDC_amp; | ||||||
916 | timebased_track->ddx_CDC = locdx_CDC; | ||||||
917 | timebased_track->ddx_CDC_amp= locdx_CDC_amp; | ||||||
918 | timebased_track->dNumHitsUsedFordEdx_CDC = locNumHitsUsedFordEdx_CDC; | ||||||
919 | |||||||
920 | // Set CDC ring & FDC plane hit patterns before candidate and wirebased tracks are associated | ||||||
921 | vector<const DCDCTrackHit*> tempCDCTrackHits; | ||||||
922 | vector<const DFDCPseudo*> tempFDCPseudos; | ||||||
923 | timebased_track->Get(tempCDCTrackHits); | ||||||
924 | timebased_track->Get(tempFDCPseudos); | ||||||
925 | timebased_track->dCDCRings = pid_algorithm->Get_CDCRingBitPattern(tempCDCTrackHits); | ||||||
926 | timebased_track->dFDCPlanes = pid_algorithm->Get_FDCPlaneBitPattern(tempFDCPseudos); | ||||||
927 | |||||||
928 | timebased_track->potential_cdc_hits_on_track = fitter->GetNumPotentialCDCHits(); | ||||||
929 | timebased_track->potential_fdc_hits_on_track = fitter->GetNumPotentialFDCHits(); | ||||||
930 | |||||||
931 | // Add DTrack object as associate object | ||||||
932 | timebased_track->AddAssociatedObject(track); | ||||||
933 | |||||||
934 | // Compute the figure-of-merit based on tracking | ||||||
935 | timebased_track->FOM = TMath::Prob(timebased_track->chisq, timebased_track->Ndof); | ||||||
936 | //_DBG_<< "FOM: " << timebased_track->FOM << endl; | ||||||
937 | |||||||
938 | _data.push_back(timebased_track); | ||||||
939 | |||||||
940 | return true; | ||||||
941 | break; | ||||||
942 | |||||||
943 | } | ||||||
944 | default: | ||||||
945 | break; | ||||||
946 | } | ||||||
947 | return false; | ||||||
948 | } | ||||||
949 | |||||||
950 | |||||||
951 | // Create a track with a mass hypothesis that was not present in the list of | ||||||
952 | // fitted tracks from an existing fitted track. | ||||||
953 | void DTrackTimeBased_factory::AddMissingTrackHypothesis(vector<DTrackTimeBased*>&tracks_to_add, | ||||||
954 | const DTrackTimeBased *src_track, | ||||||
955 | double my_mass, | ||||||
956 | double q, | ||||||
957 | JEventLoop *loop){ | ||||||
958 | |||||||
959 | // Create a new time-based track object | ||||||
960 | DTrackTimeBased *timebased_track = new DTrackTimeBased(); | ||||||
961 | *static_cast<DTrackingData*>(timebased_track) = *static_cast<const DTrackingData*>(src_track); | ||||||
962 | |||||||
963 | // Get the hits used in the fit | ||||||
964 | vector<const DCDCTrackHit *>src_cdchits; | ||||||
965 | src_track->GetT(src_cdchits); | ||||||
966 | vector<const DFDCPseudo *>src_fdchits; | ||||||
967 | src_track->GetT(src_fdchits); | ||||||
968 | |||||||
969 | // Copy over DKinematicData part from the result of a successful fit | ||||||
970 | timebased_track->setPID(IDTrack(q, my_mass)); | ||||||
971 | timebased_track->chisq = src_track->chisq; | ||||||
972 | timebased_track->Ndof = src_track->Ndof; | ||||||
973 | timebased_track->pulls = src_track->pulls; | ||||||
974 | timebased_track->extrapolations = src_track->extrapolations; | ||||||
975 | timebased_track->trackid = src_track->id; | ||||||
976 | timebased_track->candidateid=src_track->candidateid; | ||||||
977 | timebased_track->FOM=src_track->FOM; | ||||||
978 | timebased_track->cdc_hit_usage=src_track->cdc_hit_usage; | ||||||
979 | timebased_track->fdc_hit_usage=src_track->fdc_hit_usage; | ||||||
980 | timebased_track->flags=DTrackTimeBased::FLAG__USED_OTHER_HYPOTHESIS; | ||||||
981 | |||||||
982 | // Add list of start times | ||||||
983 | timebased_track->start_times.assign(src_track->start_times.begin(), | ||||||
984 | src_track->start_times.end()); | ||||||
985 | // Set the start time we used | ||||||
986 | timebased_track->setT0(timebased_track->start_times[0].t0, | ||||||
987 | timebased_track->start_times[0].t0_sigma, | ||||||
988 | timebased_track->start_times[0].system); | ||||||
989 | |||||||
990 | // Add DTrack object as associate object | ||||||
991 | vector<const DTrackWireBased*>wire_based_track; | ||||||
992 | src_track->GetT(wire_based_track); | ||||||
993 | timebased_track->AddAssociatedObject(wire_based_track[0]); | ||||||
994 | |||||||
995 | // (Partially) compensate for the difference in energy loss between the | ||||||
996 | // source track and a particle of mass my_mass | ||||||
997 | DVector3 position,momentum; | ||||||
998 | if (timebased_track->extrapolations.at(SYS_CDC).size()>0){ | ||||||
999 | unsigned int index=timebased_track->extrapolations.at(SYS_CDC).size()-1; | ||||||
1000 | position=timebased_track->extrapolations[SYS_CDC][index].position; | ||||||
1001 | momentum=timebased_track->extrapolations[SYS_CDC][index].momentum; | ||||||
1002 | } | ||||||
1003 | else if (timebased_track->extrapolations.at(SYS_FDC).size()>0){ | ||||||
1004 | unsigned int index=timebased_track->extrapolations.at(SYS_FDC).size()-1; | ||||||
1005 | position=timebased_track->extrapolations[SYS_FDC][index].position; | ||||||
1006 | momentum=timebased_track->extrapolations[SYS_FDC][index].momentum; | ||||||
1007 | } | ||||||
1008 | |||||||
1009 | DTrackFitter::fit_status_t status=DTrackFitter::kFitNotDone; | ||||||
1010 | if (momentum.Mag()>0.){ | ||||||
1011 | CorrectForELoss(position,momentum,q,my_mass); | ||||||
1012 | timebased_track->setMomentum(momentum); | ||||||
1013 | timebased_track->setPosition(position); | ||||||
1014 | // Redo the fit with the new position and momentum as initial guesses | ||||||
1015 | fitter->Reset(); | ||||||
1016 | fitter->SetFitType(DTrackFitter::kTimeBased); | ||||||
1017 | status = fitter->FindHitsAndFitTrack(*timebased_track, | ||||||
1018 | timebased_track->extrapolations,loop, | ||||||
1019 | my_mass, | ||||||
1020 | src_cdchits.size()+2*src_fdchits.size(), | ||||||
1021 | timebased_track->t0(), | ||||||
1022 | timebased_track->t0_detector()); | ||||||
1023 | // if the fit returns chisq=-1, something went terribly wrong. Do not | ||||||
1024 | // update the parameters for the track... | ||||||
1025 | if (fitter->GetChisq()<0) status=DTrackFitter::kFitFailed; | ||||||
1026 | |||||||
1027 | // if the fit flips the charge of the track, then this is bad as well | ||||||
1028 | if(q != fitter->GetFitParameters().charge()) | ||||||
1029 | status=DTrackFitter::kFitFailed; | ||||||
1030 | |||||||
1031 | // if we can't refit the track, it is likely of poor quality, so stop here and do not add the hypothesis | ||||||
1032 | if(status == DTrackFitter::kFitFailed) { | ||||||
1033 | delete timebased_track; | ||||||
1034 | return; | ||||||
1035 | } | ||||||
1036 | |||||||
1037 | if (status==DTrackFitter::kFitSuccess){ | ||||||
1038 | timebased_track->chisq = fitter->GetChisq(); | ||||||
1039 | timebased_track->Ndof = fitter->GetNdof(); | ||||||
1040 | timebased_track->pulls = std::move(fitter->GetPulls()); | ||||||
1041 | timebased_track->extrapolations=std::move(fitter->GetExtrapolations()); | ||||||
1042 | timebased_track->IsSmoothed = fitter->GetIsSmoothed(); | ||||||
1043 | *static_cast<DTrackingData*>(timebased_track) = fitter->GetFitParameters(); | ||||||
1044 | timebased_track->flags=DTrackTimeBased::FLAG__GOODFIT; | ||||||
1045 | |||||||
1046 | timebased_track->setTime(timebased_track->start_times[0].t0); | ||||||
1047 | |||||||
1048 | // Add hits used as associated objects | ||||||
1049 | const vector<const DCDCTrackHit*> &cdchits = fitter->GetCDCFitHits(); | ||||||
1050 | const vector<const DFDCPseudo*> &fdchits = fitter->GetFDCFitHits(); | ||||||
1051 | |||||||
1052 | unsigned int num_fdc_potential=fitter->GetNumPotentialFDCHits(); | ||||||
1053 | unsigned int num_cdc_potential=fitter->GetNumPotentialCDCHits(); | ||||||
1054 | |||||||
1055 | DTrackTimeBased::hit_usage_t temp; | ||||||
1056 | temp.inner_layer=0; | ||||||
1057 | temp.outer_layer=0; | ||||||
1058 | temp.total_hits=num_cdc_potential; | ||||||
1059 | if (cdchits.size()>0){ | ||||||
1060 | temp.inner_layer=cdchits[0]->wire->ring; | ||||||
1061 | temp.outer_layer=cdchits[cdchits.size()-1]->wire->ring; | ||||||
1062 | } | ||||||
1063 | timebased_track->cdc_hit_usage=temp; | ||||||
1064 | |||||||
1065 | // Reset the structure | ||||||
1066 | temp.inner_layer=0; | ||||||
1067 | temp.outer_layer=0; | ||||||
1068 | temp.total_hits=num_fdc_potential; | ||||||
1069 | if (fdchits.size()>0){ | ||||||
1070 | temp.inner_layer=fdchits[0]->wire->layer; | ||||||
1071 | temp.outer_layer=fdchits[fdchits.size()-1]->wire->layer; | ||||||
1072 | } | ||||||
1073 | timebased_track->fdc_hit_usage=temp; | ||||||
1074 | |||||||
1075 | for(unsigned int m=0; m<cdchits.size(); m++) | ||||||
1076 | timebased_track->AddAssociatedObject(cdchits[m]); | ||||||
1077 | for(unsigned int m=0; m<fdchits.size(); m++) | ||||||
1078 | timebased_track->AddAssociatedObject(fdchits[m]); | ||||||
1079 | |||||||
1080 | timebased_track->measured_cdc_hits_on_track = cdchits.size(); | ||||||
1081 | timebased_track->measured_fdc_hits_on_track = fdchits.size(); | ||||||
1082 | |||||||
1083 | // Compute the figure-of-merit based on tracking | ||||||
1084 | timebased_track->FOM = TMath::Prob(timebased_track->chisq, timebased_track->Ndof); | ||||||
1085 | |||||||
1086 | } | ||||||
1087 | } | ||||||
1088 | |||||||
1089 | if (status!=DTrackFitter::kFitSuccess){ | ||||||
1090 | for(unsigned int m=0; m<src_fdchits.size(); m++) | ||||||
1091 | timebased_track->AddAssociatedObject(src_fdchits[m]); | ||||||
1092 | for(unsigned int m=0; m<src_cdchits.size(); m++) | ||||||
1093 | timebased_track->AddAssociatedObject(src_cdchits[m]); | ||||||
1094 | |||||||
1095 | timebased_track->measured_cdc_hits_on_track = src_cdchits.size(); | ||||||
1096 | timebased_track->measured_fdc_hits_on_track = src_fdchits.size(); | ||||||
1097 | } | ||||||
1098 | |||||||
1099 | // dEdx | ||||||
1100 | double locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp; | ||||||
1101 | double locdx_CDC,locdx_CDC_amp; | ||||||
1102 | unsigned int locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC; | ||||||
1103 | pid_algorithm->CalcDCdEdx(timebased_track, locdEdx_FDC, locdx_FDC, locdEdx_CDC, locdEdx_CDC_amp,locdx_CDC,locdx_CDC_amp, locNumHitsUsedFordEdx_FDC, locNumHitsUsedFordEdx_CDC); | ||||||
1104 | |||||||
1105 | timebased_track->ddEdx_FDC = locdEdx_FDC; | ||||||
1106 | timebased_track->ddx_FDC = locdx_FDC; | ||||||
1107 | timebased_track->dNumHitsUsedFordEdx_FDC = locNumHitsUsedFordEdx_FDC; | ||||||
1108 | timebased_track->ddEdx_CDC = locdEdx_CDC; | ||||||
1109 | timebased_track->ddEdx_CDC_amp = locdEdx_CDC_amp; | ||||||
1110 | timebased_track->ddx_CDC = locdx_CDC; | ||||||
1111 | timebased_track->ddx_CDC_amp = locdx_CDC_amp; | ||||||
1112 | timebased_track->dNumHitsUsedFordEdx_CDC = locNumHitsUsedFordEdx_CDC; | ||||||
1113 | |||||||
1114 | // Set CDC ring & FDC plane hit patterns before candidate and wirebased tracks are associated | ||||||
1115 | vector<const DCDCTrackHit*> tempCDCTrackHits; | ||||||
1116 | vector<const DFDCPseudo*> tempFDCPseudos; | ||||||
1117 | timebased_track->Get(tempCDCTrackHits); | ||||||
1118 | timebased_track->Get(tempFDCPseudos); | ||||||
1119 | timebased_track->dCDCRings = pid_algorithm->Get_CDCRingBitPattern(tempCDCTrackHits); | ||||||
1120 | timebased_track->dFDCPlanes = pid_algorithm->Get_FDCPlaneBitPattern(tempFDCPseudos); | ||||||
1121 | |||||||
1122 | timebased_track->potential_cdc_hits_on_track = fitter->GetNumPotentialCDCHits(); | ||||||
1123 | timebased_track->potential_fdc_hits_on_track = fitter->GetNumPotentialFDCHits(); | ||||||
1124 | |||||||
1125 | tracks_to_add.push_back(timebased_track); | ||||||
1126 | } | ||||||
1127 | |||||||
1128 | |||||||
1129 | // If the fit failed for certain hypotheses, fill in the gaps using data from | ||||||
1130 | // successful fits for each candidate. | ||||||
1131 | bool DTrackTimeBased_factory::InsertMissingHypotheses(JEventLoop *loop){ | ||||||
1132 | if (_data.size()==0) return false; | ||||||
1133 | |||||||
1134 | // Make sure the tracks are ordered by candidate id | ||||||
1135 | sort(_data.begin(),_data.end(),DTrackTimeBased_cmp); | ||||||
1136 | |||||||
1137 | JObject::oid_t old_id=_data[0]->candidateid; | ||||||
1138 | unsigned int mass_bits=0; | ||||||
1139 | double q=_data[0]->charge(); | ||||||
1140 | bool flipped_charge=false; | ||||||
1141 | vector<DTrackTimeBased*>myhypotheses; | ||||||
1142 | vector<DTrackTimeBased*>tracks_to_add; | ||||||
1143 | for (size_t i=0;i<_data.size();i++){ | ||||||
1144 | if (_data[i]->candidateid!=old_id){ | ||||||
1145 | AddMissingTrackHypotheses(mass_bits,tracks_to_add,myhypotheses,q, | ||||||
1146 | flipped_charge,loop); | ||||||
1147 | |||||||
1148 | // Clear the myhypotheses vector for the next track | ||||||
1149 | myhypotheses.clear(); | ||||||
1150 | // Reset flags and charge | ||||||
1151 | q=_data[i]->charge(); | ||||||
1152 | flipped_charge=false; | ||||||
1153 | // Set the bit for this mass hypothesis | ||||||
1154 | mass_bits = 1<<_data[i]->PID(); | ||||||
1155 | |||||||
1156 | // Add the data to the myhypotheses vector | ||||||
1157 | myhypotheses.push_back(_data[i]); | ||||||
1158 | } | ||||||
1159 | else{ | ||||||
1160 | myhypotheses.push_back(_data[i]); | ||||||
1161 | |||||||
1162 | // Set the bit for this mass hypothesis | ||||||
1163 | mass_bits |= 1<< _data[i]->PID(); | ||||||
1164 | |||||||
1165 | // Check if the sign of the charge has flipped | ||||||
1166 | if (_data[i]->charge()!=q) flipped_charge=true; | ||||||
1167 | } | ||||||
1168 | |||||||
1169 | old_id=_data[i]->candidateid; | ||||||
1170 | } | ||||||
1171 | // Deal with last track candidate | ||||||
1172 | AddMissingTrackHypotheses(mass_bits,tracks_to_add,myhypotheses,q, | ||||||
1173 | flipped_charge,loop); | ||||||
1174 | |||||||
1175 | // Add the new list of tracks to the output list | ||||||
1176 | if (tracks_to_add.size()>0){ | ||||||
1177 | for (size_t i=0;i<tracks_to_add.size();i++){ | ||||||
1178 | _data.push_back(tracks_to_add[i]); | ||||||
1179 | } | ||||||
1180 | // Make sure the tracks are ordered by candidate id | ||||||
1181 | sort(_data.begin(),_data.end(),DTrackTimeBased_cmp); | ||||||
1182 | } | ||||||
1183 | |||||||
1184 | return true; | ||||||
1185 | } | ||||||
1186 | |||||||
1187 | // Use the FastSwim method in DReferenceTrajectory to propagate back to the | ||||||
1188 | // POCA to the beam line, adding a bit of energy at each step that would have | ||||||
1189 | // been lost had the particle emerged from the target. | ||||||
1190 | void DTrackTimeBased_factory::CorrectForELoss(DVector3 &position,DVector3 &momentum,double q,double my_mass){ | ||||||
1191 | DReferenceTrajectory::swim_step_t dummy_step; | ||||||
1192 | DReferenceTrajectory rt(fitter->GetDMagneticFieldMap(),q,&dummy_step); | ||||||
1193 | rt.SetDGeometry(geom); | ||||||
1194 | rt.SetMass(my_mass); | ||||||
1195 | rt.SetPLossDirection(DReferenceTrajectory::kBackward); | ||||||
1196 | DVector3 last_pos,last_mom; | ||||||
1197 | DVector3 origin(0.,0.,65.); | ||||||
1198 | DVector3 dir(0.,0.,1.); | ||||||
1199 | rt.FastSwim(position,momentum,last_pos,last_mom,q,origin,dir,300.); | ||||||
1200 | position=last_pos; | ||||||
1201 | momentum=last_mom; | ||||||
1202 | } | ||||||
1203 | |||||||
1204 | // Fill in all missing hypotheses for a given track candidate | ||||||
1205 | void DTrackTimeBased_factory::AddMissingTrackHypotheses(unsigned int mass_bits, | ||||||
1206 | vector<DTrackTimeBased*>&tracks_to_add, | ||||||
1207 | vector<DTrackTimeBased *>&myhypotheses, | ||||||
1208 | double q, | ||||||
1209 | bool flipped_charge, | ||||||
1210 | JEventLoop *loop){ | ||||||
1211 | |||||||
1212 | unsigned int last_index=myhypotheses.size()-1; | ||||||
1213 | unsigned int index=0; | ||||||
1214 | if (q>0){ | ||||||
1215 | if (flipped_charge){ | ||||||
1216 | /*if ((mass_bits & (1<<AntiProton))==0){ | ||||||
1217 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index], | ||||||
1218 | ParticleMass(Proton),-1.,loop); | ||||||
1219 | } | ||||||
1220 | */ | ||||||
1221 | for (unsigned int i=0;i<mass_hypotheses_negative.size();i++){ | ||||||
1222 | if ((mass_bits & (1<<mass_hypotheses_negative[i]))==0){ | ||||||
1223 | if (mass_hypotheses_negative[i]>13) index=last_index; | ||||||
1224 | else index=0; | ||||||
1225 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[index], | ||||||
1226 | ParticleMass(Particle_t(mass_hypotheses_negative[i])), | ||||||
1227 | -1.,loop); | ||||||
1228 | } | ||||||
1229 | } | ||||||
1230 | } | ||||||
1231 | /* if ((mass_bits & (1<<Proton))==0){ | ||||||
1232 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index], | ||||||
1233 | ParticleMass(Proton),+1.,loop); | ||||||
1234 | } */ | ||||||
1235 | for (unsigned int i=0;i<mass_hypotheses_positive.size();i++){ | ||||||
1236 | if ((mass_bits & (1<<mass_hypotheses_positive[i]))==0){ | ||||||
1237 | if (mass_hypotheses_positive[i]>13) index=last_index; | ||||||
1238 | else index=0; | ||||||
1239 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[index], | ||||||
1240 | ParticleMass(Particle_t(mass_hypotheses_positive[i])), | ||||||
1241 | +1.,loop); | ||||||
1242 | } | ||||||
1243 | } | ||||||
1244 | } | ||||||
1245 | else{ | ||||||
1246 | /* | ||||||
1247 | if ((mass_bits & (1<<AntiProton))==0){ | ||||||
1248 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index], | ||||||
1249 | ParticleMass(Proton),-1.,loop); | ||||||
1250 | } */ | ||||||
1251 | for (unsigned int i=0;i<mass_hypotheses_negative.size();i++){ | ||||||
1252 | if ((mass_bits & (1<<mass_hypotheses_negative[i]))==0){ | ||||||
1253 | if (mass_hypotheses_negative[i]>13) index=last_index; | ||||||
1254 | else index=0; | ||||||
1255 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[index], | ||||||
1256 | ParticleMass(Particle_t(mass_hypotheses_negative[i])), | ||||||
1257 | -1.,loop); | ||||||
1258 | } | ||||||
1259 | } | ||||||
1260 | if (flipped_charge){ | ||||||
1261 | /*if ((mass_bits & (1<<Proton))==0){ | ||||||
1262 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[last_index], | ||||||
1263 | ParticleMass(Proton),+1.,loop); | ||||||
1264 | } */ | ||||||
1265 | for (unsigned int i=0;i<mass_hypotheses_positive.size();i++){ | ||||||
1266 | if ((mass_bits & (1<<mass_hypotheses_positive[i]))==0){ | ||||||
1267 | if (mass_hypotheses_positive[i]>13) index=last_index; | ||||||
1268 | else index=0; | ||||||
1269 | AddMissingTrackHypothesis(tracks_to_add,myhypotheses[index], | ||||||
1270 | ParticleMass(Particle_t(mass_hypotheses_positive[i])), | ||||||
1271 | +1.,loop); | ||||||
1272 | } | ||||||
1273 | } | ||||||
1274 | } | ||||||
1275 | } | ||||||
1276 | } |
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 |