Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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

libraries/CCAL/DCCALShower_factory.cc

1
2/*
3 * File: DCCALHit_factory.cc
4 *
5 * Created on 11/25/18 by A.S.
6 * use structure similar to FCAL
7 */
8
9#include "CCAL/DCCALShower_factory.h"
10
11
12static mutex CCAL_MUTEX;
13//static bool CCAL_PROFILE_LOADED = false;
14
15
16//==========================================================
17//
18// Constructor
19//
20//==========================================================
21
22DCCALShower_factory::DCCALShower_factory()
23{
24 // Set defaults:
25
26 MIN_CLUSTER_BLOCK_COUNT = 2;
27 MAX_HITS_FOR_CLUSTERING = 80;
28 MIN_CLUSTER_SEED_ENERGY = 0.035; /* [GeV] */
29 MIN_CLUSTER_ENERGY = 0.05; /* [GeV] */
30 MAX_CLUSTER_ENERGY = 15.9; /* [GeV] */
31 TIME_CUT = 15.0; /* [ns] */
32
33 SHOWER_DEBUG = 0;
34 DO_NONLINEAR_CORRECTION = 1;
35
36 CCAL_RADIATION_LENGTH = 0.86;
37 CCAL_CRITICAL_ENERGY = 1.1e-3;
38
39 LOG_POS_CONST = 4.2;
40
41
42 gPARMS->SetDefaultParameter( "CCAL:SHOWER_DEBUG", SHOWER_DEBUG );
43 gPARMS->SetDefaultParameter( "CCAL:MIN_CLUSTER_BLOCK_COUNT", MIN_CLUSTER_BLOCK_COUNT,
44 "minimum number of blocks to form a cluster" );
45 gPARMS->SetDefaultParameter( "CCAL:MIN_CLUSTER_SEED_ENERGY", MIN_CLUSTER_SEED_ENERGY,
46 "minimum energy for a block to be considered as a seed for a cluster" );
47 gPARMS->SetDefaultParameter( "CCAL:MIN_CLUSTER_ENERGY", MIN_CLUSTER_ENERGY,
48 "minimum allowed cluster energy" );
49 gPARMS->SetDefaultParameter( "CCAL:MAX_CLUSTER_ENERGY", MAX_CLUSTER_ENERGY,
50 "maximum allowed cluster energy" );
51 gPARMS->SetDefaultParameter( "CCAL:MAX_HITS_FOR_CLUSTERING", MAX_HITS_FOR_CLUSTERING,
52 "maximum hits allowed to call clustering algorithm" );
53 gPARMS->SetDefaultParameter( "CCAL:TIME_CUT", TIME_CUT,
54 "time cut for associating CCAL hits together into a cluster" );
55 gPARMS->SetDefaultParameter( "CCAL:DO_NONLINEAR_CORRECTION", DO_NONLINEAR_CORRECTION,
56 "set this to zero when no nonlinear correction is desired" );
57 gPARMS->SetDefaultParameter( "CCAL:CCAL_RADIATION_LENGTH", CCAL_RADIATION_LENGTH );
58 gPARMS->SetDefaultParameter( "CCAL:CCAL_CRITICAL_ENERGY", CCAL_CRITICAL_ENERGY );
59 gPARMS->SetDefaultParameter( "CCAL:LOG_POS_CONST", LOG_POS_CONST );
60
61 VERBOSE = 0; ///< >0 once off info ; >2 event by event ; >3 everything
62 gPARMS->SetDefaultParameter("DFCALShower:VERBOSE", VERBOSE, "Verbosity level for DFCALShower objects and factories");
63}
64
65
66
67
68//==========================================================
69//
70// brun
71//
72//==========================================================
73
74jerror_t DCCALShower_factory::brun(JEventLoop *locEventLoop, int32_t runnumber)
75{
76 // Only print messages for one thread whenever run number change
77 static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } };
78 static set<int> runs_announced;
79 pthread_mutex_lock(&print_mutex);
80 bool print_messages = false;
81 if(runs_announced.find(runnumber) == runs_announced.end()){
82 print_messages = true;
83 runs_announced.insert(runnumber);
84 }
85 pthread_mutex_unlock(&print_mutex);
86
87
88 DApplication *dapp = dynamic_cast<DApplication*>(eventLoop->GetJApplication());
89 const DGeometry *geom = dapp->GetDGeometry(runnumber);
90
91 if (geom) {
92 geom->GetTargetZ(m_zTarget);
93 geom->GetCCALPosition(m_CCALdX,m_CCALdY,m_CCALfront);
94 }
95 else{
96 jerr << "No geometry accessible." << endl;
97 return RESOURCE_UNAVAILABLE;
98 }
99
100
101 //------------------------------------------------------//
102 //----------- Read in shower profile data -----------//
103
104 std::unique_lock<std::mutex> lck(CCAL_MUTEX);
105
106 string ccal_profile_file;
107 gPARMS->SetDefaultParameter("CCAL_PROFILE_FILE", ccal_profile_file,
108 "CCAL profile data file name");
109
110 // follow similar procedure as other resources (DMagneticFieldMapFineMesh)
111
112 map< string,string > profile_file_name;
113 JCalibration *jcalib = dapp->GetJCalibration(runnumber);
114
115 if( jcalib->GetCalib("/CCAL/profile_data/profile_data_map", profile_file_name) )
116 {
117 jout << "Can't find requested /CCAL/profile_data/profile_data_map in CCDB for this run!"
118 << endl;
119
120 } else if( profile_file_name.find("map_name") != profile_file_name.end()
121 && profile_file_name["map_name"] != "None" )
122 {
123 JResourceManager *jresman = dapp->GetJResourceManager(runnumber);
124 ccal_profile_file = jresman->GetResource(profile_file_name["map_name"]);
125 }
126
127 if(print_messages)
128 jout<<"Reading CCAL profile data from "<<ccal_profile_file<<" ..."<<endl;
129
130 // check to see if we actually have a file
131 if(ccal_profile_file.empty())
132 {
133 if(print_messages)
134 jerr << "Empty file..." << endl;
135 return RESOURCE_UNAVAILABLE;
136 }
137
138 ifstream ccal_profile(ccal_profile_file.c_str());
139 for(int i=0; i<=500; i++) {
140 for(int j=0; j<=i; j++) {
141 int id1, id2;
142 double fcell_hyc, fd2c;
143
144 ccal_profile >> id1 >> id2 >> fcell_hyc >> fd2c;
145
146 acell[id1][id2] = fcell_hyc;
147 acell[id2][id1] = fcell_hyc;
148 ad2c[id1][id2] = fd2c;
149 ad2c[id2][id1] = fd2c;
150 }
151 }
152 ccal_profile.close();
153
154 lck.unlock();
155
156
157
158
159 //------------------------------------------------------//
160 //---------- Initialize channel status array ----------//
161
162 for(int icol = 0; icol < MCOL12; ++icol) {
163 for(int irow = 0; irow < MROW12; ++irow) {
164 if(icol>=5 && icol<=6 && irow>=5 && irow<=6) { stat_ch[irow][icol] = -1; }
165 else { stat_ch[irow][icol] = 0; }
166 }
167 }
168
169
170
171
172 //------------------------------------------------------//
173 //---------- Read shower timewalk parameters ----------//
174
175 vector< vector<double> > timewalk_params;
176 if( eventLoop->GetCalib("/CCAL/shower_timewalk_correction",timewalk_params) )
177 jout << "Error loading /CCAL/shower_timewalk_correction !" << endl;
178 else {
179 if( (int)timewalk_params.size() != 2 ) {
180 cout << "DCCALShower_factory: Wrong number of entries to timewalk correction table (should be 144)." << endl;
181 for( int ii = 0; ii < 2; ++ii ) {
182 timewalk_p0.push_back(0.0);
183 timewalk_p1.push_back(0.0);
184 timewalk_p2.push_back(0.0);
185 timewalk_p3.push_back(0.0);
186 }
187 } else {
188 for( vector< vector<double> >::const_iterator iter = timewalk_params.begin();
189 iter != timewalk_params.end(); ++iter ) {
190 if( iter->size() != 4 ) {
191 cout << "DCCALShower_factory: Wrong number of values in timewalk correction table (should be 4)" << endl;
192 continue;
193 }
194
195 timewalk_p0.push_back( (*iter)[0] );
196 timewalk_p1.push_back( (*iter)[1] );
197 timewalk_p2.push_back( (*iter)[2] );
198 timewalk_p3.push_back( (*iter)[3] );
199
200 }
201 }
202 }
203
204
205
206
207 //------------------------------------------------------//
208 //--------- Read in non-linearity parameters ----------//
209
210 vector< vector<double> > nonlin_params;
211 if( eventLoop->GetCalib("/CCAL/nonlinear_energy_correction",nonlin_params) )
212 jout << "Error loading /CCAL/nonlinear_energy_correction !" << endl;
213 else {
214 if( (int)nonlin_params.size() != CCAL_CHANS ) {
215 cout << "DCCALShower_factory: Wrong number of entries to nonlinear energy correction table (should be 144)." << endl;
216 for( int ii = 0; ii < CCAL_CHANS; ++ii ) {
217 Nonlin_p0.push_back(0.0);
218 Nonlin_p1.push_back(0.0);
219 Nonlin_p2.push_back(0.0);
220 Nonlin_p3.push_back(0.0);
221 }
222 } else {
223 for( vector< vector<double> >::const_iterator iter = nonlin_params.begin();
224 iter != nonlin_params.end(); ++iter ) {
225 if( iter->size() != 4 ) {
226 cout << "DCCALShower_factory: Wrong number of values in nonlinear energy correction table (should be 4)" << endl;
227 continue;
228 }
229
230 Nonlin_p0.push_back( (*iter)[0] );
231 Nonlin_p1.push_back( (*iter)[1] );
232 Nonlin_p2.push_back( (*iter)[2] );
233 Nonlin_p3.push_back( (*iter)[3] );
234
235 }
236 }
237 }
238
239 if( SHOWER_DEBUG ) {
240 cout << "\n\nNONLIN_P0 NONLIN_P1 NONLIN_P2 NONLIN_P3" << endl;
241 for(int ii = 0; ii < (int)Nonlin_p0.size(); ii++) {
242 cout << Nonlin_p0[ii] << " " << Nonlin_p1[ii] << " " << Nonlin_p2[ii] << " " <<
243 Nonlin_p3[ii] << endl;
244 }
245 cout << "\n\n";
246 }
247
248
249
250
251 return NOERROR;
252}
253
254
255
256
257//==========================================================
258//
259// evnt
260//
261//==========================================================
262
263jerror_t DCCALShower_factory::evnt(JEventLoop *locEventLoop, uint64_t eventnumber)
264{
265
266
267 vector< const DCCALGeometry* > ccalGeomVect;
268 locEventLoop->Get( ccalGeomVect );
1
Calling 'JEventLoop::Get'
269 if (ccalGeomVect.size() < 1)
270 return OBJECT_NOT_AVAILABLE;
271 const DCCALGeometry& ccalGeom = *(ccalGeomVect[0]);
272
273
274
275
276 //------- Get the CCALHits and organize hit pattern -------//
277
278
279 vector< const DCCALHit* > ccalhits;
280 locEventLoop->Get( ccalhits );
281
282 int n_hits = static_cast<int>( ccalhits.size() );
283 if( n_hits < 1 || n_hits > MAX_HITS_FOR_CLUSTERING ) return NOERROR;
284
285
286 vector< vector< const DCCALHit* > > hitPatterns;
287 getHitPatterns( ccalhits, hitPatterns );
288
289 int n_patterns = static_cast<int>( hitPatterns.size() );
290 if( n_patterns < 1 ) return NOERROR;
291
292 vector< ccalcluster_t > ccalClusters; // will hold all clusters
293 vector< cluster_t > clusterStorage; // will hold the constituents of every cluster
294
295
296
297
298 //------- Call island clusterizer on each pattern -------//
299
300
301 for( int ipat = 0; ipat < n_patterns; ipat++ )
302 {
303
304
305 /*----- prepare data in dimensionless format -----*/
306
307 vector< const DCCALHit* > rawHitPattern = hitPatterns[ipat];
308 vector< const DCCALHit* > locHitPattern;
309 cleanHitPattern( rawHitPattern, locHitPattern );
310
311 int n_hits = static_cast<int>( locHitPattern.size() );
312
313 vector< int > ia;
314 vector< int > id;
315
316 for( int ih = 0; ih < n_hits; ih++ ) {
317 const DCCALHit *ccalhit = locHitPattern[ih];
318 int row = 12 - ccalhit->row;
319 int col = 12 - ccalhit->column;
320 int ie = static_cast<int>( ccalhit->E*10. + 0.5 );
321 if( ie > 0 ) {
322 int address = 100*col + row;
323 ia.push_back( address );
324 id.push_back( ie );
325 }
326 }
327
328
329 /*------------- call to island -------------*/
330
331 vector< gamma_t > gammas; gammas.clear();// Output of main_island (holds reconstructed photons)
332 main_island( ia, id, gammas );
333
334
335 /*------------ post-island processing ------------*/
336
337 int init_clusters = static_cast<int>( gammas.size() );
338 if( !init_clusters ) continue;
339
340 processShowers( gammas, ccalGeom, locHitPattern, eventnumber,
341 ccalClusters, clusterStorage );
342
343
344 } // end looping over hit patterns
345
346
347
348
349 //-------------- Fill DCCALShower Object --------------//
350
351 int n_clusters = static_cast<int>( ccalClusters.size() );
352
353 for( int k = 0; k < n_clusters; k++ ) {
354
355 DCCALShower *shower = new DCCALShower;
356
357 shower->E = ccalClusters[k].E;
358 shower->Esum = ccalClusters[k].Esum;
359
360 shower->x = ccalClusters[k].x+m_CCALdX;
361 shower->y = ccalClusters[k].y+m_CCALdY;
362 shower->x1 = ccalClusters[k].x1+m_CCALdX;
363 shower->y1 = ccalClusters[k].y1+m_CCALdY;
364 shower->z = m_CCALfront;
365
366 shower->chi2 = ccalClusters[k].chi2;
367 shower->sigma_E = ccalClusters[k].sigma_E;
368 shower->Emax = ccalClusters[k].emax;
369 shower->time = ccalClusters[k].time;
370
371 shower->dime = ccalClusters[k].nhits;
372 shower->idmax = ccalClusters[k].idmax;
373 shower->id = ccalClusters[k].id;
374
375 shower->type = ccalClusters[k].type;
376
377 int showTypeVal = (ccalClusters[k].type)/10;
378 shower->ClusterType = static_cast<ClusterType_t>( showTypeVal/2 );
379 shower->PeakType = static_cast<PeakType_t>( showTypeVal%2 );
380 //shower->ExyztCovariance(i, j)
381 float xerr = 0.1016;// / sqrt(ccalClusters[k].E) + 0.2219; // HARD CODED VALUE!!!!
382 float yerr = 0.1016;// / sqrt(ccalClusters[k].E) + 0.2219; // HARD CODED VALUE!!!!
383 float zerr = 2.5; // HARD CODED VALUE!!!!
384 float terr = 0.2; // HARD CODED VALUE!!!!
385 float eerr = 0.5;//pow(ccalClusters[k].E, 2) * (0.01586 / ccalClusters[k].E + 0.0002342 / pow(ccalClusters[k].E, 2) + 1.696e-6); // HARD CODED VALUE!!!!
386 //copy xyz errors into covariance matrix
387 shower->ExyztCovariance.ResizeTo(5,5);
388 for (int col = 0; col < 5; col ++) {
389 for (int row = 0; row < 5; row ++) {
390 if (col != row) shower->ExyztCovariance[col][row] = 0;
391 }
392 }
393 shower->ExyztCovariance[0][0] = pow(xerr, 2);
394 shower->ExyztCovariance[1][1] = pow(yerr, 2);
395 shower->ExyztCovariance[2][2] = pow(zerr, 2);
396 shower->ExyztCovariance[3][3] = pow(terr, 2);
397 shower->ExyztCovariance[4][4] = pow(eerr, 2);
398
399 if (VERBOSE>2) {printf("(E,x,y,z,t) "); shower->ExyztCovariance.Print(); }
400
401 for( int icell = 0; icell < ccalClusters[k].nhits; icell++ ) {
402
403 int hitID = clusterStorage[k].id[icell];
404 float hitX = ccalGeom.positionOnFace( hitID ).X();
405 float hitY = ccalGeom.positionOnFace( hitID ).Y();
406 int hitROW = ccalGeom.row( hitY );
407 int hitCOL = ccalGeom.column( hitX );
408
409 DCCALHit *clusHit = new DCCALHit;
410 clusHit->row = hitROW;
411 clusHit->column = hitCOL;
412 clusHit->x = hitX;
413 clusHit->y = hitY;
414 clusHit->E = static_cast<float>( 1000.*clusterStorage[k].E[icell] );
415 clusHit->t = static_cast<float>( clusterStorage[k].t[icell] );
416
417 shower->AddAssociatedObject( clusHit );
418
419 }
420
421 _data.push_back( shower );
422 }
423
424
425 return NOERROR;
426
427}
428
429
430
431
432//==========================================================
433//
434// getHitPatterns
435//
436//==========================================================
437
438void DCCALShower_factory::getHitPatterns( vector< const DCCALHit* > hitarray,
439 vector< vector< const DCCALHit* > > &hitPatterns )
440{
441
442 /*------------------------------
443
444 Method for sorting hit patterns:
445
446 1. Find hit with largest energy.
447 2. Sort hit vector in order of increasing time-difference from this hit
448 3. Push all hits within 15 ns of max hit to a new vector (first few elements of sorted vec)
449 4. Erase the elements that were moved from the previous vector
450 - maybe steps 3&4 can be done simultaneously?
451 5. Push the new vector back to the hitPatterns vector
452 6. Repeat steps 1-5 until no hits remain in original hitarray
453
454 --------------------------------*/
455
456
457 int n_hits = static_cast<int>( hitarray.size() );
458
459 if( n_hits < 1 ) return;
460 if( n_hits < 2 ) {
461 vector< const DCCALHit* > hitVec;
462 hitVec.push_back( hitarray[0] );
463 hitPatterns.push_back( hitVec );
464 return;
465 }
466
467
468 vector< const DCCALHit* > clonedHitArray = hitarray;
469
470 while( clonedHitArray.size() )
471 {
472
473 vector< const DCCALHit* > locHitVec;
474
475 float maxE = -1.;
476 float maxT = 1.e6;
477
478 for( unsigned int ih = 0; ih < clonedHitArray.size(); ih++ ) {
479 float trialE = clonedHitArray[ih]->E;
480 if( trialE > maxE ) { maxE = trialE; maxT = clonedHitArray[ih]->t; }
481 }
482
483 if( maxE < 0. ) break;
484
485
486 sortByTime( clonedHitArray, maxT );
487
488
489 n_hits = static_cast<int>( clonedHitArray.size() );
490
491 int n_good_hits = 0;
492 for( int ih = 0; ih < n_hits; ih++ ) {
493
494 const DCCALHit *locHit = clonedHitArray[ih];
495 float timeDiff = fabs( locHit->t - maxT );
496
497 if( timeDiff < TIME_CUT ) {
498 locHitVec.push_back( locHit );
499 n_good_hits++;
500 } else { break; }
501
502 }
503
504 if( locHitVec.size() ) hitPatterns.push_back( locHitVec );
505
506 clonedHitArray.erase( clonedHitArray.begin(), clonedHitArray.begin() + n_good_hits );
507
508 }
509
510
511 return;
512
513}
514
515
516
517
518//==========================================================
519//
520// sortByTime
521//
522//==========================================================
523
524void DCCALShower_factory::sortByTime( vector< const DCCALHit* > &hitarray, float hitTime )
525{
526
527 int nhits = static_cast<int>( hitarray.size() );
528
529 if( nhits < 2 ) return; // nothing to sort
530
531 for( int ih = 1; ih < nhits; ih++ )
532 {
533
534 float timeDiff = fabs( hitarray[ih]->t - hitTime );
535 float lastTimeDiff = fabs( hitarray[ih-1]->t - hitTime );
536
537 if( timeDiff <= lastTimeDiff )
538 {
539
540 const DCCALHit *Hit = hitarray[ih];
541
542 for( int ii = ih-1; ii >= -1; ii-- ) {
543
544 if( ii >= 0 ) {
545
546 const DCCALHit *locHit = hitarray[ii];
547 float locTimeDiff = fabs( locHit->t - hitTime );
548
549 if( timeDiff < locTimeDiff ) {
550 hitarray[ii+1] = locHit;
551 } else {
552 hitarray[ii+1] = Hit;
553 break;
554 }
555 } else {
556 hitarray[0] = Hit;
557 }
558 }
559
560 } // end if statement
561
562 } // end loop over hits
563
564 return;
565}
566
567
568
569
570//==========================================================
571//
572// cleanHitPattern
573//
574//==========================================================
575
576void DCCALShower_factory::cleanHitPattern( vector< const DCCALHit* > hitarray,
577 vector< const DCCALHit* > &hitarrayClean )
578{
579
580 for( vector< const DCCALHit* >::const_iterator iHit = hitarray.begin();
581 iHit != hitarray.end(); ++iHit ) {
582
583 int id12 = ((*iHit)->row)*12 + (*iHit)->column;
584 int findVal = -1;
585 for( vector<const DCCALHit*>::size_type ii = 0; ii != hitarrayClean.size(); ++ii ) {
586 int id = 12*(hitarrayClean[ii]->row) + hitarrayClean[ii]->column;
587 if( id == id12 ) { findVal = (int)ii; break; }
588 }
589 if( findVal >= 0 ) {
590 if( (*iHit)->E > hitarrayClean[findVal]->E ) {
591 hitarrayClean.erase( hitarrayClean.begin()+findVal );
592 hitarrayClean.push_back( (*iHit) );
593 }
594 } else {
595 hitarrayClean.push_back( (*iHit) );
596 }
597
598 }
599
600 return;
601
602}
603
604
605
606
607//==========================================================
608//
609// processShowers
610//
611//==========================================================
612
613void DCCALShower_factory::processShowers( vector< gamma_t > gammas, DCCALGeometry ccalGeom,
614 vector< const DCCALHit* > locHitPattern, int eventnumber,
615 vector< ccalcluster_t > &ccalClusters, vector< cluster_t > &clusterStorage )
616{
617
618
619 //------------- Do some post-island processing -------------//
620
621
622 int n_clusters = 0;
623 int n_hits = static_cast<int>( locHitPattern.size() );
624
625 int init_clusters = static_cast<int>( gammas.size() );
626 for( int k = 0; k < init_clusters; k++ ) {
627
628 ccalcluster_t locCluster; // stores cluster parameters
629 cluster_t locClusterStorage; // stores hit information of cluster cells
630
631 int type = gammas[k].type;
632 int dime = gammas[k].dime;
633 int id = gammas[k].id;
634 double chi2 = gammas[k].chi2;
635 double e = gammas[k].energy;
636 double x = gammas[k].x;
637 double y = gammas[k].y;
638 double xc = gammas[k].xc;
639 double yc = gammas[k].yc;
640
641
642 // check that shower is not just a single module and that energy is reasonable:
643
644 if( dime < MIN_CLUSTER_BLOCK_COUNT ) { continue; }
645 if( e < MIN_CLUSTER_ENERGY || e > MAX_CLUSTER_ENERGY ) { continue; }
646
647 n_clusters++;
648
649
650 //------------ Find cell with max energy ------------//
651
652 double ecellmax = -1; int idmax = -1;
653 double e1 = 0.0;
654 for( int j = 0; j < (dime>MAX_CC60 ? MAX_CC60 : dime); j++ ) {
655
656
657 double ecell = 1.e-4*static_cast<double>( gammas[k].icl_en[j] );
658
659 int ccal_id = gammas[k].icl_in[j];
660 int kx = 12 - (ccal_id/100), ky = 12 - (ccal_id%100);
661
662 ccal_id = ky*12 + kx;
663
664 e1 += ecell;
665 if( ecell > ecellmax ) {
666 ecellmax = ecell;
667 idmax = ccal_id;
668 }
669
670 }
671
672 double xmax = ccalGeom.positionOnFace(idmax).X();
673 double ymax = ccalGeom.positionOnFace(idmax).Y();
674
675
676 //----------- Loop over constituent hits ------------//
677
678 double sW = 0.0;
679 double xpos = 0.0;
680 double ypos = 0.0;
681 double W;
682
683 for( int j = 0; j < (dime>MAX_CC60 ? MAX_CC60 : dime); j++ ) {
684
685 int ccal_id = gammas[k].icl_in[j];
686 int kx = 12 - (ccal_id/100), ky = 12 - (ccal_id%100);
687 ccal_id = ky*12 + kx;
688
689 double ecell = 1.e-4*static_cast<double>( gammas[k].icl_en[j] );
690 double xcell = ccalGeom.positionOnFace( ccal_id ).X();
691 double ycell = ccalGeom.positionOnFace( ccal_id ).Y();
692
693 if(id%10 == 1 || id%10 == 2) {
694 xcell += xc;
695 ycell += yc;
696 }
697
698 double hittime = 0.;
699 for( int ihit = 0; ihit < n_hits; ihit++ ) {
700 int trialid = 12*( locHitPattern[ihit]->row) + locHitPattern[ihit]->column;
701 if( trialid == ccal_id ) {
702 hittime = locHitPattern[ihit]->t;
703 break;
704 }
705 }
706
707 locClusterStorage.id[j] = ccal_id;
708 locClusterStorage.E[j] = ecell;
709 locClusterStorage.x[j] = xcell;
710 locClusterStorage.y[j] = ycell;
711 locClusterStorage.t[j] = hittime;
712
713
714 // The shower position is calculated using logarithmic weighting:
715
716 if( ecell > 0.009 && fabs(xcell-xmax) < 6. && fabs(ycell-ymax) < 6.) {
717 W = LOG_POS_CONST + log(ecell/e);
718 if( W > 0 ) {
719 sW += W;
720 xpos += xcell*W;
721 ypos += ycell*W;
722 }
723 }
724
725 }
726
727 for( int j = dime; j < MAX_CC60; j++ ) // zero the rest
728 locClusterStorage.id[j] = -1;
729
730 double weightedTime = getEnergyWeightedTime( locClusterStorage, dime );
731 double showerTime = getCorrectedTime( weightedTime, e );
732
733
734
735 //------- Get position at surface of Calorimeter -------//
736
737 DVector3 vertex(0.0, 0.0, m_zTarget); // for now, use center of target as vertex
738
739 double x1, y1;
740 double zV = vertex.Z();
741 double z0 = m_CCALfront - zV;
742 if(sW) {
743 double dz = getShowerDepth( e );
744 double zk = 1. / (1. + dz/z0);
745 x1 = zk*xpos/sW;
746 y1 = zk*ypos/sW;
747 } else {
748 printf("WRN bad cluster log. coord at event %i: center id = %i, energy = %f\n",
749 eventnumber, idmax, e);
750 x1 = 0.0;
751 y1 = 0.0;
752 }
753
754
755
756
757 //-------- Calculate nonlinear-corrected energy --------//
758
759
760 if( idmax < 0 ) {
761 printf("WRN negative idmax recorded at event %i; energy = %f\n", eventnumber, e);
762 }
763
764 double ecorr = e;
765 if( DO_NONLINEAR_CORRECTION ) ecorr = getCorrectedEnergy( e, idmax );
766
767 if( SHOWER_DEBUG ) {
768 cout << "\n\nShower energy before correction: " << e << " GeV" << endl;
769 cout << "Shower energy after correction: " << ecorr << " GeV\n\n" << endl;
770 }
771
772
773
774
775 //-------- Get energy resolution (needs updating) --------//
776
777 double se = sqrt( 0.9*0.9*ecorr*ecorr + 2.5*2.5*ecorr + 1.0 );
778 // from HYCAL reconstruction, need to tune
779 se /= 100.;
780
781 if( (type%10)==1 )
782 se *= 1.5;
783 else if( (type%10)==2 )
784 se *= 1.25;
785
786
787
788 //----------------- Fill cluster bank -----------------//
789
790 locCluster.type = type;
791 locCluster.nhits = dime;
792 locCluster.id = id;
793 locCluster.idmax = idmax;
794
795 locCluster.E = ecorr;
796 locCluster.Esum = e1;
797 locCluster.x = x;
798 locCluster.y = y;
799 locCluster.x1 = x1;
800 locCluster.y1 = y1;
801 locCluster.chi2 = chi2;
802 locCluster.time = showerTime;
803 locCluster.emax = ecellmax;
804 locCluster.sigma_E = se;
805
806 clusterStorage.push_back( locClusterStorage );
807 ccalClusters.push_back( locCluster );
808
809 }
810
811
812 return;
813}
814
815
816
817
818//==========================================================
819//
820// getEnergyWeightedTime
821//
822//==========================================================
823
824double DCCALShower_factory::getEnergyWeightedTime( cluster_t clusterStorage, int nHits )
825{
826
827 double weightedtime = 0.;
828 double totEn = 0;
829 for( int j = 0; j < (nHits > MAX_CC60 ? MAX_CC60 : nHits); j++ ) {
830 weightedtime += clusterStorage.t[j]*clusterStorage.E[j];
831 totEn += clusterStorage.E[j];
832 }
833 weightedtime /= totEn;
834
835 return weightedtime;
836
837}
838
839
840
841
842//==========================================================
843//
844// getCorrectedTime
845//
846//==========================================================
847
848double DCCALShower_factory::getCorrectedTime( double time, double energy )
849{
850 // timewalk correction:
851
852 int iPar;
853 if( energy < 1.0 ) iPar = 0;
854 else iPar = 1;
855
856 double dt = timewalk_p0[iPar]*exp( timewalk_p1[iPar] + timewalk_p2[iPar]*energy ) + timewalk_p3[iPar];
857 double t_cor = time - dt;
858
859 return t_cor;
860
861}
862
863
864
865
866//==========================================================
867//
868// getShowerDepth
869//
870//==========================================================
871
872double DCCALShower_factory::getShowerDepth( double energy )
873{
874
875 double z0 = CCAL_RADIATION_LENGTH, e0 = CCAL_CRITICAL_ENERGY;
876 double depth = (energy > 0.) ? z0*log(1.+energy/e0) : 0.;
877 return depth;
878
879}
880
881
882
883
884//==========================================================
885//
886// getCorrectedEnergy
887//
888//==========================================================
889
890double DCCALShower_factory::getCorrectedEnergy( double energy, int id )
891{
892
893 if( id < 0 ) return energy;
894
895 if( Nonlin_p1[id] == 0. && Nonlin_p2[id] == 0. && Nonlin_p3[id] == 0.) return energy;
896 if( Nonlin_p0[id] == 0. ) return energy;
897 //if( energy < 0.5 || energy > 12. ) return energy;
898
899
900 double emin = 0., emax = 12.;
901 double e0 = (emin+emax)/2.;
902
903 double de1 = energy - emin*nonlin_func( emin, id );
904 double de2 = energy - emax*nonlin_func( emax, id );
905 double de = energy - e0*nonlin_func( e0, id );
906
907 while( fabs(emin-emax) > 1.e-5 ) {
908 if( de1*de > 0. && de2*de < 0.) {
909 emin = e0;
910 de1 = energy - emin*nonlin_func( emin, id );
911 } else {
912 emax = e0;
913 de2 = energy - emax*nonlin_func( emax, id );
914 }
915 e0 = (emin+emax)/2.;
916 de = energy - e0*nonlin_func( e0, id );
917 }
918
919 return e0;
920
921}
922
923
924
925
926//==========================================================
927//
928// nonlin_func
929//
930//==========================================================
931
932double DCCALShower_factory::nonlin_func( double e, int id )
933{
934
935 return pow( (e/Nonlin_p0[id]), Nonlin_p1[id] + Nonlin_p2[id]*e + Nonlin_p3[id]*e*e );
936
937}
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963//==========================================================
964//
965// main_island()
966//
967//==========================================================
968
969void DCCALShower_factory::main_island( vector<int> &ia, vector<int> &id, vector<gamma_t> &gammas )
970{
971
972 //----------------------------------------------
973 // Initialize some useful variables:
974
975 int nhits; // number of hits in detector
976 int ncl; // number of clusters
977 vector<int> lencl; // length of a cluster
978
979
980 nhits = static_cast<int>(ia.size());
981 if( nhits == 0 ) return;
982
983 /*
984 The vector 'ia' will hold the addresses of modules that were hit.
985 They're defined as 100*(i+1)+(j+1) where i is column and j is row of the hit module.
986 Row 0, column 0 is bottom right corner of CCAL (looking upstream).
987
988 The 'id' vector holds the energies of the hit modules (in units of 0.1 MeVs).
989 */
990
991
992 //------------------ Search for clusters: ------------------//
993
994
995 ncl = clus_hyc( nhits, ia, id, lencl );
996
997 /*
998 At this point, the vectors ia and id are sorted such that they are grouped
999 together by simply-connected clusters. For example, the first lencl[0] elements of ia give
1000 the addresses of the elements in the first cluster. The next lencl[1] elements
1001 after that give the addresses of the elements in the second cluster.
1002
1003 The clusters here are just created by grouping everything that is physically
1004 next to each other into one cluster - all simply-connected cells are joined in a cluster.
1005 */
1006
1007
1008 //-------------------- Process Cluster: --------------------//
1009
1010 int nadcgam = 0; // number of found clusters
1011
1012 if( ncl <= 0 ) return;
1013
1014 int ipncl = 0;
1015 for( int icl = 0; icl < ncl; icl++ ) {
1016
1017 int ecl = 0;
1018 for( int ii = 0; ii < lencl[icl]; ii++ )
1019 ecl += id[ipncl+ii];
1020 if( ecl > MIN_ENERGY0. ) {
1021
1022 vector< int > icl_a; // addresses of current cluster
1023 vector< int > icl_d; // energies of current cluster
1024
1025 icl_a.insert( icl_a.begin(), ia.begin()+ipncl, ia.begin()+ipncl+lencl[icl] );
1026 icl_d.insert( icl_d.begin(), id.begin()+ipncl, id.begin()+ipncl+lencl[icl] );
1027
1028
1029 if( SHOWER_DEBUG ) {
1030
1031 cout << "\n\n======================" << endl;
1032 cout << "Processing Cluster " << icl << ":" << endl;
1033 for( unsigned int ih = 0; ih < icl_a.size(); ih++ ) {
1034 cout << icl_a[ih] << " " << icl_d[ih] << endl;
1035 }
1036
1037 }
1038
1039 int before = nadcgam;
1040 gams_hyc( lencl[icl], icl_a, icl_d, nadcgam, gammas );
1041 int after = nadcgam;
1042
1043
1044 if( SHOWER_DEBUG ) {
1045 cout << "Reconstructed " << after-before << " gammas. \n\n" << endl;
1046 }
1047
1048
1049 if( nadcgam > MADCGAM50 ) {
1050 nadcgam = MADCGAM50;
1051 break;
1052 }
1053 }
1054 ipncl = ipncl + lencl[icl];
1055 }
1056
1057
1058 //-------------------- Prepare gammas for final processing --------------------//
1059
1060
1061 // convert position to units of cm:
1062
1063 for( int ig = 0; ig < nadcgam; ig++ ) {
1064 gammas[ig].energy /= 10000.;
1065 gammas[ig].x = (static_cast<double>(MCOL12+1)-2.*gammas[ig].x)*xsize2.09/2.;
1066 gammas[ig].y = (static_cast<double>(MROW12+1)-2.*gammas[ig].y)*ysize2.09/2.;
1067 gammas[ig].xc = -gammas[ig].xc*xsize2.09;
1068 gammas[ig].yc = -gammas[ig].yc*ysize2.09;
1069 }
1070
1071
1072 if( nadcgam < 1 ) return;
1073
1074
1075 // sort gammas in order of decreasing energy:
1076
1077 for( int ig = 1; ig < nadcgam; ig++ )
1078 {
1079 if( gammas[ig].energy > gammas[ig-1].energy ) {
1080 gamma_t ref_gam = gammas[ig];
1081
1082 for( int ii = ig-1; ii >= -1; ii-- ) {
1083 if( ii >= 0 ) {
1084 if( ref_gam.energy > gammas[ii].energy ) {
1085 gammas[ii+1] = gammas[ii];
1086 } else {
1087 gammas[ii+1] = ref_gam;
1088 break;
1089 }
1090 } else {
1091 gammas[0] = ref_gam;
1092 }
1093 }
1094 }
1095 }
1096
1097
1098
1099 return;
1100}
1101
1102
1103
1104
1105
1106//==========================================================
1107//
1108// clus_hyc
1109//
1110//==========================================================
1111
1112int DCCALShower_factory::clus_hyc( int nw, vector<int> &ia, vector<int> &id, vector<int> &lencl )
1113{
1114
1115 //---------------- Local Declarations ---------------//
1116
1117 int maxcl = 200; // maximumum number of clusters allowed
1118 int ncl; // number of clusters
1119 int next, iak; //
1120 int ib, ie; //
1121 int ias, iaf; //
1122 int last, lastcl; //
1123 int leng; //
1124 //
1125 int loclencl[200]; // stores the lengths of clusters locally
1126
1127
1128 //---------------- Event Analysis Code --------------//
1129
1130 ncl = 0;
1131 if( nw < 1 ) return ncl;
1132 if( nw < 2 ) { // if only one hit
1133 ncl = 1;
1134 lencl.push_back(1);
1135 return ncl;
1136 }
1137
1138 order_hyc( nw, ia, id ); // sort the addresses (ia) in increasing order
1139
1140 ncl = 0;
1141 next = 0;
1142
1143 for( int k = 1; k < (nw+1); k++ ) {
1144
1145 if( k < nw ) iak = ia[k];
1146 if( (iak-ia[k-1] <= 1) && (k < nw) ) continue;
1147
1148 ib = next;
1149 ie = k-1;
1150 next = k;
1151
1152 if( ncl >= maxcl ) return ncl;
1153 ncl++;
1154
1155 loclencl[ncl-1] = next-ib;
1156 if(ncl == 1) continue;
1157
1158 ias = ia[ib];
1159 iaf = ia[ie];
1160 last = ib-1;
1161 lastcl = ncl-1;
1162
1163 for( int icl = lastcl; icl > 0; icl-- ) {
1164
1165 leng = loclencl[icl-1];
1166 if( (ias-ia[last]) > 100 ) break; // no subclusters to be glued
1167
1168 for( int ii = last; ii >= last-leng+1; ii-- ) {
1169 if( ( ias-ia[ii] ) > 100 ) break;
1170 if( ( iaf-ia[ii] ) >= 100 ) {
1171
1172 if( (icl < (ncl-1)) && (leng <= 10800) ) {
1173
1174 vector< int > iawork;
1175 ucopy1( ia, iawork, last-leng+1, leng );
1176 ucopy2( ia, last+1, last+1-leng, ib-last-1 );
1177 ucopy3( iawork, ia, ib-leng, leng );
1178
1179 vector< int > idwork;
1180 ucopy1( id, idwork, last-leng+1, leng );
1181 ucopy2( id, last+1, last+1-leng, ib-last-1 );
1182 ucopy3( idwork, id, ib-leng, leng );
1183
1184 for( int jj = icl; jj < ncl-1; jj++ ) {
1185 loclencl[jj-1] = loclencl[jj];
1186 }
1187
1188 }
1189
1190 ib = ib-leng;
1191 loclencl[ncl-2] = loclencl[ncl-1]+leng;
1192 ncl = ncl-1;
1193 break;
1194 }
1195 }
1196
1197 last = last-leng;
1198
1199 } // end loop over previous subclusters
1200 } // end loop over all hits
1201
1202 for( int icl = 0; icl < ncl; icl++ ) {
1203 lencl.push_back( loclencl[icl] );
1204 }
1205
1206
1207 return ncl;
1208}
1209
1210
1211
1212
1213
1214//==========================================================
1215//
1216// order_hyc
1217//
1218//==========================================================
1219
1220void DCCALShower_factory::order_hyc( int nw, vector<int> &ia, vector<int> &id )
1221{
1222 // sort ia and id in order of increasing address
1223
1224 if( nw < 2 ) return; // only one hit
1225
1226 for( int k = 1; k < nw; k++ ) { // loop over hits
1227
1228 if( ia[k] <= ia[k-1] ) { // check if address is less than previous entry
1229 int iak = ia[k];
1230 int idk = id[k];
1231
1232 for( int ii = k-1; ii >= -1; ii = ii-1 ) { // loop over the previous entries
1233
1234 if( ii >= 0 ) {
1235 if( iak < ia[ii] ) {
1236 ia[ii+1] = ia[ii];
1237 id[ii+1] = id[ii];
1238 } else {
1239 ia[ii+1] = iak;
1240 id[ii+1] = idk;
1241 break;
1242 }
1243 } else {
1244 ia[0] = iak;
1245 id[0] = idk;
1246 }
1247
1248 } // end loop over previous entries
1249 } // endif
1250 } // end loop over hits
1251
1252
1253 return;
1254}
1255
1256
1257
1258
1259
1260//==========================================================
1261//
1262// gams_hyc
1263//
1264//==========================================================
1265
1266void DCCALShower_factory::gams_hyc( int nadc, vector<int> &ia, vector<int> &id,
1267 int &nadcgam, vector<gamma_t> &gammas )
1268{
1269
1270 //-------------Local Declarations------------//
1271
1272 int ngam0; // number of gammas found before
1273 int niter; // max number of iterations (6)
1274 int npk; // number of peaks in the cluster
1275 int ipnpk[10]; // counter number with max energy in a peak
1276 int igmpk[2][10]; //
1277 int minpk; // min energy of a counter in a cluster
1278 int idelta; //
1279 int itype; // type of peak
1280 int leng; //
1281 int ixypk, ixpk, iypk; //
1282 int ic, idc, in; //
1283 int ixy, ixymax, ixymin; //
1284 int ix, iy, iyc; //
1285 int iwk; //
1286 int iia; //
1287 int ide; //
1288 int idecorr; //
1289
1290 double fw[13];
1291 double chisq; // current value of chi2
1292 double chisq1; // value of chi2 for preliminary gammas separation
1293 double chisq2; // value of chi2 for final gammas separation
1294 double ratio; //
1295 double eg; //
1296 double epk[10]; //
1297 double xpk[10]; //
1298 double ypk[10]; //
1299 double a, dx, dy; //
1300 double e1, x1, y1; //
1301 double e2, x2, y2; //
1302 double fe, fia; //
1303
1304 int idsum;
1305
1306 idelta = 0;
1307 chisq1 = 90.;
1308 chisq2 = 50.;
1309 niter = 6;
1310
1311 ngam0 = nadcgam;
1312
1313
1314
1315 vector<int> iwrk[13]; // working array for resolved peaks
1316 vector<int> idp[13]; // energy of each cell of the island belonging to each peak
1317 vector<double> fwrk[13]; // working array for resolved peaks
1318
1319 // allocate memory for each vector:
1320
1321 for( int ii=0; ii<13; ii++ ) {
1322 iwrk[ii].reserve(nadc);
1323 fwrk[ii].reserve(nadc);
1324 idp[ii].reserve(nadc);
1325 for( int ih=0; ih<nadc; ih++ ) {
1326 iwrk[ii].push_back(0);
1327 fwrk[ii].push_back(0.);
1328 idp[ii].push_back(0);
1329 }
1330 }
1331
1332
1333
1334
1335 //------------------------------------------
1336 // peaks search:
1337
1338 order_hyc( nadc, ia, id );
1339
1340 idsum = 0;
1341 for( int ic = 0; ic < nadc; ic++ )
1342 idsum += id[ic];
1343
1344 if( nadc < 3 )
1345 minpk = 1;
1346 else {
1347 int trial = 7.*log(1. + 0.0001*static_cast<double>(idsum)) + 0.5;
1348 if( trial > 1 ) minpk = trial;
1349 else minpk = 1;
1350 }
1351 minpk *= 100;
1352
1353
1354 npk = 0;
1355
1356 for( ic = 0; ic < nadc; ic++ ) {
1357 idc = id[ic];
1358 if( idc < minpk ) continue;
1359 ixy = ia[ic];
1360 ixymax = ixy + 100 + 1;
1361 ixymin = ixy - 100 - 1;
1362 iyc = ixy - (ixy/100)*100;
1363
1364 int peakVal = 1;
1365
1366 in = ic+1;
1367 while( in < nadc && ia[in] <= ixymax ) {
1368 iy = ia[in] - (ia[in]/100)*100;
1369 if( abs(iy-iyc) <= 1 && id[in] >= idc ) peakVal = 0;
1370 in++;
1371 }
1372
1373 in = ic-1;
1374 while( in >= 0 && ia[in] >= ixymin ) {
1375 iy = ia[in] - (ia[in]/100)*100;
1376 if( abs(iy-iyc) <= 1 && id[in] > idc ) peakVal = 0;
1377 in -= 1;
1378 }
1379
1380 if( !peakVal ) continue;
1381
1382 npk += 1;
1383 ipnpk[npk-1] = ic;
1384 if( npk == 10 || npk >= 10000/nadc-3 ) break;
1385
1386 }
1387
1388 if( npk <= 0 ) return;
1389
1390 if( SHOWER_DEBUG ) cout << "Found " << npk << " peaks. Now processing..." << endl;
1391
1392 //------------------------------------------
1393 // gammas search for one peak:
1394
1395 if( npk == 1 ) {
1396
1397 if( nadcgam >= MADCGAM50-1 ) return;
1398 nadcgam = nadcgam+1;
1399 chisq = chisq2;
1400
1401 ic = ipnpk[0];
1402 ix = ia[ic]/100;
1403 iy = ia[ic] - ix*100;
1404
1405 itype = peak_type( ix, iy );
1406
1407 e2 = 0.;
1408 gamma_hyc( nadc, ia, id, chisq,
1409 e1, x1, y1,
1410 e2, x2, y2 );
1411
1412 gamma_t gam1;
1413 gamma_t gam2;
1414
1415 gam1.type = itype;
1416 gam1.dime = nadc;
1417 gam1.id = 0;
1418
1419 gam1.chi2 = chisq;
1420 gam1.energy = e1;
1421 gam1.x = x1;
1422 gam1.y = y1;
1423 gam1.xc = 0.;
1424 gam1.yc = 0.;
1425
1426 if( e2 > 0. && nadcgam <= MADCGAM50-1 ) {
1427 nadcgam = nadcgam+1;
1428
1429 gam2.type = itype+10;
1430 gam2.dime = nadc;
1431 gam2.id = 2;
1432
1433 gam2.chi2 = chisq;
1434 gam2.energy = e2;
1435 gam2.x = x2;
1436 gam2.y = y2;
1437 gam2.xc = 0.5*(x2-x1);
1438 gam2.yc = 0.5*(y2-y1);
1439
1440 gam1.type = itype+10;
1441 gam1.id = 1;
1442 gam1.xc = 0.5*(x1-x2);
1443 gam1.yc = 0.5*(y1-y2);
1444
1445 for( int jj = 0; jj < nadc; jj++ ) {
1446 if( jj < MAX_CC60 ) {
1447 gam1.icl_in[jj] = ia[jj];
1448 gam2.icl_in[jj] = ia[jj];
1449 gam1.icl_en[jj] = static_cast<int>(static_cast<double>(id[jj])*e1/(e1+e2) + 0.5);
1450 gam2.icl_en[jj] = static_cast<int>(static_cast<double>(id[jj])*e2/(e1+e2) + 0.5);
1451 }
1452 }
1453
1454 gammas.push_back( gam1 );
1455 gammas.push_back( gam2 );
1456
1457 } else {
1458 for( int jj = 0; jj < nadc; jj++ ) {
1459 if( jj < MAX_CC60 ) {
1460 gam1.icl_in[jj] = ia[jj];
1461 gam1.icl_en[jj] = id[jj];
1462 }
1463 }
1464
1465 gammas.push_back( gam1 );
1466
1467 }
1468
1469
1470 } else { // cluster with more than one peak
1471
1472 //------------------------------------------
1473 /*
1474 First step - 1 gamma in each peak.
1475 Do a preliminary estimation of (E,x,y) of each peak, and split each peak into two hits
1476 only if it is badly needed (chi2 improvement is too high).
1477 If this split occurs, it is only for better (E,x,y) estimation, as it will be
1478 rejoined and reanalyzed in the second step.
1479 */
1480 //------------------------------------------
1481
1482
1483 if( nadcgam >= MADCGAM50-1 ) return;
1484
1485 ratio = 1.;
1486 for( int iter = 0; iter < niter; iter++ ) {
1487 for( int ii = 0; ii < nadc; ii++ ) {
1488 iwrk[0].push_back(0);
1489 fwrk[0].push_back(0.);
1490 }
1491
1492 for( int ipk = 0; ipk < npk; ipk++ ) {
1493
1494 ic = ipnpk[ipk];
1495 if( iter > 0 ) ratio = fwrk[ipk+1][ic]/fwrk[npk+1][ic];
1496 eg = ratio*static_cast<double>(id[ic]);
1497 ixypk = ia[ic];
1498 ixpk = ixypk/100;
1499 iypk = ixypk - ixpk*100;
1500 epk[ipk] = eg;
1501 xpk[ipk] = eg*static_cast<double>(ixpk);
1502 ypk[ipk] = eg*static_cast<double>(iypk);
1503
1504 if( ic < nadc-1 ) {
1505 for( int ii = ic+1; ii < nadc; ii++ ) {
1506 ixy = ia[ii];
1507 ix = ixy/100;
1508 iy = ixy - ix*100;
1509 if( ixy-ixypk > 100+1 ) break;
1510 if( abs(iy-iypk) <= 1 ) {
1511 if( iter != 0 ) ratio = fwrk[ipk+1][ii]/fwrk[npk+1][ii];
1512 eg = ratio*static_cast<double>(id[ii]);
1513 epk[ipk] = epk[ipk] + eg;
1514 xpk[ipk] = xpk[ipk] + eg*static_cast<double>(ix);
1515 ypk[ipk] = ypk[ipk] + eg*static_cast<double>(iy);
1516 }
1517 }
1518 }
1519
1520 if( ic > 0 ) {
1521 for( int ii = ic-1; ii >= 0; ii--) {
1522 ixy = ia[ii];
1523 ix = ixy/100;
1524 iy = ixy - ix*100;
1525 if( ixypk-ixy > 100+1 ) break;
1526 if( abs(iy-iypk) <= 1 ) {
1527 if( iter != 0 ) ratio = fwrk[ipk+1][ii]/fwrk[npk+1][ii];
1528 eg = ratio*static_cast<double>(id[ii]);
1529 epk[ipk] = epk[ipk] + eg;
1530 xpk[ipk] = xpk[ipk] + eg*static_cast<double>(ix);
1531 ypk[ipk] = ypk[ipk] + eg*static_cast<double>(iy);
1532 }
1533 }
1534 }
1535
1536 if( epk[ipk] > 0. ) {
1537 xpk[ipk] = xpk[ipk]/epk[ipk];
1538 ypk[ipk] = ypk[ipk]/epk[ipk];
1539 }
1540
1541 for( int ii = 0; ii < nadc; ii++ ) {
1542 ixy = ia[ii];
1543 ix = ixy/100;
1544 iy = ixy - ix*100;
1545 dx = fabs( static_cast<double>(ix) - xpk[ipk] );
1546 dy = fabs( static_cast<double>(iy) - ypk[ipk] );
1547
1548 a = epk[ipk]*cell_hyc( dx, dy );
1549
1550 fwrk[ipk+1][ii] = a;
1551 fwrk[0][ii] = fwrk[0][ii] + fwrk[ipk+1][ii];
1552 iwrk[ipk+1][ii] = static_cast<int>(a + 0.5);
1553 iwrk[0][ii] = iwrk[0][ii] + iwrk[ipk+1][ii];
1554 }
1555
1556
1557 } // end loop over peaks
1558
1559 for( int ii = 0; ii < nadc; ii++ ) {
1560 iwk = iwrk[0][ii];
1561 if( iwk < 1 ) iwk = 1;
1562 iwrk[npk+1][ii] = iwk;
1563
1564 if( fwrk[0][ii] > 1.e-2 )
1565 fwrk[npk+1][ii] = fwrk[0][ii];
1566 else
1567 fwrk[npk+1][ii] = 1.e-2;
1568
1569 }
1570 } // end of iterations to separate peaks in a cluster
1571
1572
1573
1574 if( SHOWER_DEBUG ) {
1575
1576
1577 cout << "\n\n\nAfter 6 iterations: " << endl;
1578 for( int ipk = 0; ipk < npk; ipk++ ) {
1579 cout << "peak " << ipk+1 << ": " << endl;
1580 for( int jj = 0; jj < nadc; jj++ ) {
1581 cout << ia[jj] <<"; "<< id[jj] <<"; "<< fwrk[ipk+1][jj] << endl;
1582 }
1583 }
1584
1585 }
1586
1587
1588
1589
1590 for( int ipk = 0; ipk < npk; ipk++ ) {
1591
1592 vector<int> iwrk_a;
1593 vector<int> iwrk_d;
1594
1595 leng = 0;
1596 for( int ii = 0; ii < nadc; ii++ ) {
1597 if( fwrk[0][ii] > 1.e-2 ) {
1598 ixy = ia[ii];
1599 fe = static_cast<double>(id[ii])*fwrk[ipk+1][ii]/fwrk[0][ii];
1600
1601 if( fe > idelta ) {
1602 leng = leng+1;
1603 iwrk_a.push_back( ixy );
1604 iwrk_d.push_back( static_cast<int>(fe+0.5) );
1605 }
1606
1607 }
1608 }
1609
1610 if( nadcgam >= MADCGAM50-1 ) return;
1611
1612 igmpk[1][ipk] = 0;
1613 if( leng == 0 ) continue;
1614 nadcgam = nadcgam + 1;
1615 chisq = chisq1;
1616
1617 ic = ipnpk[ipk];
1618 ix = ia[ic]/100;
1619 iy = ia[ic] - ix*100;
1620
1621 itype = peak_type( ix, iy );
1622
1623 e2 = 0.;
1624 gamma_hyc( leng, iwrk_a, iwrk_d, chisq,
1625 e1, x1, y1, e2, x2, y2 );
1626
1627 gamma_t gam1;
1628 gamma_t gam2;
1629
1630 gam1.chi2 = chisq;
1631 gam1.type = itype+40;
1632 gam1.energy = e1;
1633 gam1.x = x1;
1634 gam1.y = y1;
1635 gam1.dime = leng;
1636
1637 gam1.id = 90;
1638
1639 igmpk[0][ipk] = nadcgam;
1640 igmpk[1][ipk] = nadcgam;
1641
1642 if( e2 > 0. && nadcgam <= MADCGAM50-1 ) {
1643 nadcgam = nadcgam+1;
1644
1645 gam2.chi2 = chisq;
1646 gam2.type = itype+50;
1647 gam2.energy = e2;
1648 gam2.x = x2;
1649 gam2.y = y2;
1650 gam2.xc = 0.5*(x2-x1);
1651 gam2.yc = 0.5*(y2-y1);
1652 gam1.xc = 0.5*(x1-x2);
1653 gam1.yc = 0.5*(y1-y2);
1654
1655 gam2.id = 92;
1656 gam1.id = 91;
1657
1658 gam2.dime = leng;
1659 igmpk[1][ipk] = nadcgam;
1660
1661 gammas.push_back( gam1 );
1662 gammas.push_back( gam2 );
1663
1664 } else { gammas.push_back( gam1 ); }
1665
1666 } // end loop over peaks
1667
1668
1669
1670 /*
1671 This is the second step: ( 1 or 2 gamma in each peak )
1672 (e,x,y) of hits were preliminarily estimated in the first step.
1673 */
1674
1675 for( int ii = 0; ii < nadc; ii++ ) {
1676 iwrk[0][ii] = 0;
1677 fwrk[0][ii] = 0.;
1678 idp[0][ii] = 0;
1679 }
1680
1681 for( int ipk = 0; ipk < npk; ipk++ ) {
1682 for( int ii = 0; ii < nadc; ii++ ) {
1683 iwrk[ipk+1][ii] = 0;
1684 fwrk[ipk+1][ii] = 0.;
1685 idp[ipk+1][ii] = 0;
1686
1687 if( igmpk[1][ipk] == 0 ) continue;
1688
1689 for( int ig = igmpk[0][ipk]; ig <= igmpk[1][ipk]; ig++ ) {
1690 ixy = ia[ii];
1691 ix = ixy/100;
1692 iy = ixy-(ix*100);
1693 dx = static_cast<double>(ix) - gammas[ig-1].x;
1694 dy = static_cast<double>(iy) - gammas[ig-1].y;
1695
1696 fia = gammas[ig-1].energy*cell_hyc( dx, dy );
1697 iia = static_cast<int>(fia+0.5);
1698
1699 // part of gamma 'ig' energy belonging to cell 'i' from peak 'ipk':
1700 iwrk[ipk+1][ii] += iia;
1701 fwrk[ipk+1][ii] += fia;
1702 idp[ipk+1][ii] += iia;
1703
1704 iwrk[0][ii] += iia;
1705 fwrk[0][ii] += fia;
1706
1707 }
1708
1709 } // end loop over hits
1710 } // end loop over peaks
1711
1712
1713
1714
1715 // Recover working array and renormalize total sum to the original cell energy:
1716
1717 for( int ii = 0; ii < nadc; ii++ ) {
1718
1719 idp[0][ii] = 0;
1720 for( int ipk = 0; ipk < npk; ipk++ ) {
1721 idp[0][ii] += idp[ipk+1][ii];
1722 }
1723
1724 ide = id[ii] - idp[0][ii];
1725 if( ide == 0 ) continue;
1726 if( fwrk[0][ii] == 0. ) continue;
1727
1728 for( int ipk = 0; ipk < npk; ipk++ ) {
1729 fw[ipk+1] = fwrk[ipk+1][ii]/fwrk[0][ii];
1730 }
1731
1732 idecorr = 0;
1733 for( int ipk = 0; ipk < npk; ipk++ ) {
1734 fia = ide*fw[ipk+1];
1735 if( (fwrk[ipk+1][ii] + fia) > 0. ) {
1736 fwrk[ipk+1][ii] += fia;
1737 fwrk[0][ii] += fia;
1738 }
1739 iia = static_cast<int>(fia+0.5);
1740 if( (iwrk[ipk+1][ii] + iia) > 0 ) {
1741 iwrk[ipk+1][ii] += iia;
1742 iwrk[0][ii] += iia;
1743 idecorr += iia;
1744 } else if( (iwrk[ipk+1][ii] + iia) < 0 ) {
1745 //cout << "WARNING NEGATIVE CORR: ia = " << ia[ii] << "; id = " << id[ii] << endl;
1746 }
1747 } // end loop over peaks
1748
1749 } // end loop over hits
1750
1751
1752
1753 // erase the gammas found in the previous step:
1754
1755 nadcgam = ngam0;
1756 gammas.erase( gammas.begin()+nadcgam, gammas.end() );
1757
1758
1759
1760
1761
1762
1763 for( int ipk = 0; ipk < npk; ipk++ ) {
1764 leng = 0;
1765
1766 vector<int> iwrk_a;
1767 vector<int> iwrk_d;
1768
1769 for( int ii = 0; ii < nadc; ii++ ){
1770 if( iwrk[0][ii] > 0 ) {
1771 fe = id[ii]*fwrk[ipk+1][ii]/fwrk[0][ii];
1772 if( fe > idelta ) {
1773 leng++;
1774 iwrk_a.push_back( ia[ii] );
1775 iwrk_d.push_back( static_cast<int>(fe+0.5) );
1776 }
1777 }
1778 }
1779
1780 if( nadcgam >= MADCGAM50-1 ) return;
1781
1782
1783 if( leng == 0 ) continue;
1784
1785 nadcgam++;
1786
1787 chisq = chisq2;
1788
1789 ic = ipnpk[ipk];
1790 ix = ia[ic]/100;
1791 iy = ia[ic] - ix*100;
1792
1793 itype = peak_type( ix, iy );
1794
1795 e2 = 0.;
1796 gamma_hyc( leng, iwrk_a, iwrk_d, chisq,
1797 e1, x1, y1, e2, x2, y2 );
1798
1799 gamma_t gam1;
1800 gamma_t gam2;
1801
1802 gam1.type = itype+20;
1803 gam1.dime = leng;
1804 gam1.id = 10;
1805
1806 gam1.chi2 = chisq;
1807 gam1.energy = e1;
1808 gam1.x = x1;
1809 gam1.y = y1;
1810 gam1.xc = 0.;
1811 gam1.yc = 0.;
1812
1813 if( e2 > 0. && nadcgam <= MADCGAM50-1 ) {
1814 nadcgam = nadcgam+1;
1815
1816 gam2.type = itype+30;
1817 gam2.dime = leng;
1818 gam2.id = 12;
1819
1820 gam2.chi2 = chisq;
1821 gam2.energy = e2;
1822 gam2.x = x2;
1823 gam2.y = y2;
1824 gam2.xc = 0.5*(x2-x1);
1825 gam2.yc = 0.5*(y2-y1);
1826
1827 gam1.type = itype+30;
1828 gam1.id = 11;
1829 gam1.xc = 0.5*(x1-x2);
1830 gam1.yc = 0.5*(x1-x2);
1831
1832 for( int jj = 0; jj < leng; jj++ ) {
1833 if( jj < MAX_CC60 ) {
1834 gam1.icl_in[jj] = iwrk_a[jj];
1835 gam2.icl_in[jj] = iwrk_a[jj];
1836 gam1.icl_en[jj] = static_cast<int>(
1837 static_cast<double>(iwrk_d[jj])*e1/(e1+e2) + 0.5 );
1838 gam2.icl_en[jj] = static_cast<int>(
1839 static_cast<double>(iwrk_d[jj])*e2/(e1+e2) + 0.5 );
1840 }
1841 }
1842
1843 gammas.push_back( gam1 );
1844 gammas.push_back( gam2 );
1845
1846 } else {
1847 for( int jj = 0; jj < leng; jj++ ) {
1848 if( jj < MAX_CC60 ) {
1849 gam1.icl_in[jj] = iwrk_a[jj];
1850 gam1.icl_en[jj] = iwrk_d[jj];
1851 }
1852 }
1853
1854 gammas.push_back( gam1 );
1855
1856 }
1857
1858
1859 } // end loop over peaks
1860
1861
1862
1863 } // end looping over multi-peak cluster
1864
1865
1866
1867
1868
1869 return;
1870}
1871
1872
1873
1874
1875
1876//==========================================================
1877//
1878// peak_type
1879//
1880//==========================================================
1881
1882int DCCALShower_factory::peak_type( int ix, int iy )
1883{
1884 /*
1885 itype = 2 : if the peak is in the most outer layer
1886 itype = 1 : if the peak is in the most inner layer
1887 itype = 0 : if the peak is anywhere else
1888 */
1889
1890 int itype = 0;
1891 if( (ix == MCOL12/2-1 || ix == MCOL12/2+2) && (iy >= MROW12/2-1 && iy <= MROW12/2+2) ) itype = 1;
1892 if( (iy == MROW12/2-1 || iy == MROW12/2+2) && (ix >= MCOL12/2-1 && ix <= MCOL12/2+2) ) itype = 1;
1893 if( ix == 1 || ix == MCOL12 || iy == 1 || iy == MROW12 ) itype = 2;
1894
1895 return itype;
1896}
1897
1898
1899
1900
1901
1902//==========================================================
1903//
1904// gamma_hyc
1905//
1906//==========================================================
1907
1908void DCCALShower_factory::gamma_hyc( int nadc, vector<int> ia, vector<int> id, double &chisq,
1909 double &e1, double &x1, double &y1,
1910 double &e2, double &x2, double &y2 )
1911{
1912 //-------------Local Declarations------------//
1913
1914 int dof;
1915
1916 double dxy; // initial step for iteration
1917 double stepmin; // minimum step for iteration
1918 double stepx, stepy; // current steps
1919 double parx, pary; //
1920 double chimem, chisq0, chi0; //
1921 double chiold; //
1922 double chi00; //
1923 double x0, y0; //
1924 double ee, xx, yy; //
1925 double d2, xm2, xm2cut; //
1926 double chir, chil, chiu, chid; //
1927
1928 dxy = 0.05;
1929 stepmin = 0.002;
1930 xm2cut = 1.7;
1931
1932 int nzero;
1933 vector<int> iaz;
1934
1935 //-------------Event Analysis Code------------//
1936
1937 e2 = 0.;
1938 x2 = 0.;
1939 y2 = 0.;
1940
1941
1942 fill_zeros( nadc, ia, nzero, iaz );
1943 mom1_pht( nadc, ia, id, nzero, iaz, e1, x1, y1 ); // calculate initial values of (E,x,y)
1944
1945 if( nadc <= 0 ) return;
1946
1947 chimem = chisq;
1948 chisq1_hyc( nadc, ia, id, nzero, iaz, e1, x1, y1, chi0 ); // initial value of chi2
1949
1950
1951 chisq0 = chi0;
1952 dof = nzero + nadc - 2;
1953 if( dof < 1 ) dof = 1;
1954 chisq = chi0/dof;
1955 x0 = x1;
1956 y0 = y1;
1957
1958
1959 // start of iterations
1960
1961 int rounds = 0;
1962 while( 1 ) {
1963
1964 chisq1_hyc( nadc, ia, id, nzero, iaz, e1, x0+dxy, y0, chir );
1965 chisq1_hyc( nadc, ia, id, nzero, iaz, e1, x0-dxy, y0, chil );
1966 chisq1_hyc( nadc, ia, id, nzero, iaz, e1, x0, y0+dxy, chiu );
1967 chisq1_hyc( nadc, ia, id, nzero, iaz, e1, x0, y0-dxy, chid );
1968
1969 if( chi0 > chir || chi0 > chil ) {
1970 stepx = dxy;
1971 if( chir > chil ) stepx = -stepx;
1972 } else {
1973 stepx = 0.;
1974 parx = chir + chil - 2.*chi0;
1975 if( parx > 0. ) stepx = -dxy*(chir-chil)/(2.*parx);
1976 }
1977 if( chi0 > chiu || chi0 > chid ) {
1978 stepy = dxy;
1979 if( chiu > chid ) stepy = -stepy;
1980 } else {
1981 stepy = 0.;
1982 pary = chiu + chid - 2.*chi0;
1983 if( pary > 0. ) stepy = -dxy*(chiu-chid)/(2.*pary);
1984 }
1985
1986
1987 // if steps at minimum, end iterations
1988
1989 if( fabs(stepx) < stepmin && fabs(stepy) < stepmin ) break;
1990
1991 chisq1_hyc( nadc, ia, id, nzero, iaz, e1, x0+stepx, y0+stepy, chi00 );
1992
1993 // if chi2 at minimum, end iterations
1994
1995 if( chi00 >= chi0 ) break;
1996
1997 chi0 = chi00;
1998 x0 = x0+stepx;
1999 y0 = y0+stepy;
2000
2001 rounds++;
2002 if( rounds > 10000 ) { cout << "max rounds" << endl; break; }
2003
2004 }
2005
2006 if( chi0 < chisq0 ) { // if chi2 improved, then fix the improved values
2007 x1 = x0;
2008 y1 = y0;
2009 chisq = chi0/dof;
2010 }
2011
2012 // if chi2 is less than maximum allowed for one gamma in a peak, return.
2013 // otherwise, try separating the peak into two gammas:
2014
2015 if( chisq <= chimem ) return;
2016
2017 chiold = chisq;
2018 tgamma_hyc( nadc, ia, id, nzero, iaz, chisq, ee, xx, yy, e2, x2, y2 );
2019
2020 if( e2 > 0. ) { // if chi2 improved, decide if the separation
2021 // has physical meaning by calculating the
2022 // effective mass of the two gammas
2023
2024 d2 = pow((xx-x2)*xsize2.09, 2.0) + pow((yy-y2)*ysize2.09, 2.0);
2025 xm2 = ee*e2*d2;
2026
2027 if( xm2 > 0. ) xm2 = sqrt(xm2)/1270.*0.1; // mass in MeV; 1270 = zccal
2028
2029 if( xm2 > xm2cut*xsize2.09 ) { // if the separation has physical meaning
2030 e1 = ee; // fix the parameters of the first gamma
2031 x1 = xx;
2032 y1 = yy;
2033 } else { // if no physical meaning e2=0
2034 e2 = 0.; // (second gamma is killed)
2035 chisq = chiold;
2036 }
2037 }
2038
2039 return;
2040}
2041
2042
2043
2044
2045
2046//==========================================================
2047//
2048// fill_zeros
2049//
2050//==========================================================
2051
2052void DCCALShower_factory::fill_zeros( int nadc, vector<int> ia, int &nneib, vector<int> &iaz )
2053{
2054
2055 int ix, iy, nneibnew;
2056 vector<int> ian;
2057
2058 nneib = 0;
2059 for( int ii = 0; ii < nadc; ii++ ) {
2060 ix = ia[ii]/100;
2061 iy = ia[ii] - ix*100;
2062
2063 if( ix > 1 ) { // fill left neib
2064 nneib = nneib+1;
2065 ian.push_back(iy + (ix-1)*100);
2066
2067 if( iy > 1 ) { // fill bottom left neib
2068 nneib = nneib+1;
2069 ian.push_back(iy-1 + (ix-1)*100);
2070 }
2071 if( iy < MROW12 ) { // fill top left neib
2072 nneib = nneib+1;
2073 ian.push_back(iy+1 + (ix-1)*100);
2074 }
2075 }
2076 if( ix < MCOL12 ) {
2077 nneib = nneib+1;
2078 ian.push_back(iy + (ix+1)*100);
2079
2080 if( iy > 1 ) { // fill bottom right neib
2081 nneib = nneib+1;
2082 ian.push_back(iy-1 + (ix+1)*100);
2083 }
2084 if( iy < MROW12 ) { // fill top right neib
2085 nneib = nneib+1;
2086 ian.push_back(iy+1 + (ix+1)*100);
2087 }
2088 }
2089
2090 if( iy > 1 ) { // fill bottom neib
2091 nneib = nneib+1;
2092 ian.push_back(iy-1 + ix*100);
2093 }
2094 if( iy < MROW12 ) { // fill top neib
2095 nneib = nneib+1;
2096 ian.push_back(iy+1 + ix*100);
2097 }
2098 }
2099
2100
2101 for( int ii = 0; ii < nneib; ii++ ) {
2102 for( int jj = 0; jj < nadc; jj++ ) {
2103 if( ia[jj] == ian[ii] ) ian[ii] = -1;
2104 }
2105 }
2106
2107 for( int ii = 0; ii < nneib; ii++ ) {
2108 if( ian[ii] == -1 ) continue;
2109 for( int jj = ii+1; jj < nneib; jj++ ) {
2110 if( ian[jj] == ian[ii] ) ian[jj] = -1;
2111 }
2112 }
2113
2114 nneibnew = 0;
2115 for( int ii = 0; ii < nneib; ii++ ) {
2116 ix = ian[ii]/100;
2117 iy = ian[ii] - ix*100;
2118 if( ian[ii] != -1 ) {
2119 if( stat_ch[iy-1][ix-1] == 0 ) {
2120 nneibnew = nneibnew+1;
2121 iaz.push_back( ian[ii] );
2122 }
2123 }
2124 }
2125 nneib = nneibnew;
2126
2127
2128 return;
2129}
2130
2131
2132
2133
2134
2135//==========================================================
2136//
2137// mom1_pht
2138//
2139//==========================================================
2140
2141void DCCALShower_factory::mom1_pht( int nadc, vector<int> ia, vector<int> id,
2142 int nzero, vector<int> iaz, double &e1, double &x1, double &y1 )
2143{
2144 //-------------Local Declarations------------//
2145
2146 int ix, iy;
2147 double dx, dy;
2148
2149 double a; //
2150 double corr; // correction to energy
2151
2152 //--------------Event Analysis Code-------------//
2153
2154 e1 = 0.;
2155 x1 = 0.;
2156 y1 = 0.;
2157
2158 if( nadc <= 0 ) return;
2159 for( int ii = 0; ii < nadc; ii++ ) {
2160 a = static_cast<double>(id[ii]);
2161 ix = ia[ii]/100;
2162 iy = ia[ii] - ix*100;
2163 e1 = e1 + a;
2164 x1 = x1 + a*static_cast<double>(ix);
2165 y1 = y1 + a*static_cast<double>(iy);
2166 }
2167 if( e1 <= 0. ) return;
2168 x1 = x1/e1;
2169 y1 = y1/e1;
2170 corr = 0.;
2171 for( int ii = 0; ii < nadc; ii++ ) {
2172 ix = ia[ii]/100;
2173 iy = ia[ii] - ix*100;
2174 dx = static_cast<double>(ix) - x1;
2175 dy = static_cast<double>(iy) - y1;
2176 corr = corr + cell_hyc( dx, dy );
2177 }
2178
2179 if( COUNT_ZERO1 ) {
2180 for( int ii = 0; ii < nzero; ii++ ) {
2181 ix = iaz[ii]/100;
2182 iy = iaz[ii] - ix*100;
2183 dx = static_cast<double>(ix) - x1;
2184 dy = static_cast<double>(iy) - y1;
2185 corr = corr + cell_hyc( dx, dy );
2186 }
2187 }
2188
2189 corr = corr/1.006;
2190 if( SHOWER_DEBUG ) cout << "e, corr = " << e1 << ", " << corr << endl;
2191
2192
2193 if( corr < 0.8 ) {
2194 if( SHOWER_DEBUG ) {
2195 cout << "corr = " << corr << ", " << e1 << ", " << x1 << ", " << y1;
2196 cout << "! Too many around central hole!" << endl;
2197 }
2198 corr = 0.8;
2199 } else if( corr > 1.0 ) {
2200 corr = 1.;
2201 }
2202 e1 = e1/corr;
2203
2204
2205 return;
2206}
2207
2208
2209
2210
2211
2212//==========================================================
2213//
2214// chisq1_hyc
2215//
2216//==========================================================
2217
2218void DCCALShower_factory::chisq1_hyc( int nadc, vector<int> ia, vector<int> id,
2219 int nneib, vector<int> iaz, double e1, double x1, double y1, double &chisq )
2220{
2221 //-------------Local Declarations------------//
2222
2223 int ix, iy;
2224 double dx, dy;
2225 double fa, fcell;
2226
2227
2228 //--------------Event Analysis Code-------------//
2229
2230 chisq = 0.;
2231
2232 for( int ii = 0; ii < nadc; ii++ ) {
2233 fa = static_cast<double>(id[ii]);
2234 ix = ia[ii]/100;
2235 iy = ia[ii] - ix*100;
2236 dx = x1 - static_cast<double>(ix);
2237 dy = y1 - static_cast<double>(iy);
2238 if( e1 != 0. ) {
2239 if( fabs(dx) <= 6.0 && fabs(dy) <= 6.0 ) {
2240 fcell = cell_hyc( dx, dy );
2241 chisq = chisq + e1*pow((fcell-(fa/e1)), 2.)/sigma2(dx, dy, fcell, e1);
2242 }
2243 } else {
2244 chisq = chisq + fa*fa/9.;
2245 cout << "case 0 ch" << endl;
2246 //if( SHOWER_DEBUG ) cout << "case 0 ch" << endl;
2247 }
2248 }
2249
2250 for(int ii = 0; ii < nneib; ii++ ) {
2251 ix = iaz[ii]/100;
2252 iy = iaz[ii] - ix*100;
2253 dx = x1 - static_cast<double>(ix);
2254 dy = y1 - static_cast<double>(iy);
2255 if( e1 != 0. ) {
2256 if( fabs(dx) < 6.0 && fabs(dy) < 6.0 ) {
2257 fcell = cell_hyc( dx, dy );
2258 chisq = chisq + e1*fcell*fcell/sigma2(dx, dy, fcell, e1);
2259 }
2260 } else {
2261 chisq = chisq + id[ii]*id[ii]/9.;
2262 //if( SHOWER_DEBUG ) cout << "case 0 ch" << endl;
2263 }
2264 }
2265
2266
2267 return;
2268}
2269
2270
2271
2272
2273
2274//==========================================================
2275//
2276// sigma2, d2c, & cell_hyc
2277//
2278//==========================================================
2279
2280double DCCALShower_factory::sigma2( double dx, double dy, double fc, double e )
2281{
2282 double sig2;
2283 double alp = 0.816;
2284 double bet1 = 32.1;
2285 double bet2 = 1.72;
2286
2287 double r = dx*dx + dy*dy;
2288 if( r > 25. ) {
2289 sig2 = 100.;
2290 return sig2;
2291 }
2292
2293 sig2 = alp*fc + (bet1 + bet2*sqrt(e/100.))*d2c( dx, dy ) + 0.2/(e/100.);
2294 if( TEST_P1 ) sig2 = sig2/pow(0.0001*e, 0.166);
2295 sig2 *= 100.;
2296
2297 return sig2;
2298}
2299
2300
2301double DCCALShower_factory::d2c( double dx, double dy )
2302{
2303 int i, j;
2304 double ax, ay, wx, wy;
2305 double d2c;
2306
2307 ax = fabs(dx*100.);
2308 ay = fabs(dy*100.);
2309 i = int(ax);
2310 j = int(ay);
2311
2312 if( i < 499 && j < 499 && i >= 0 && j >= 0 ) {
2313 //if( i < 500. && j < 500. ) {
2314
2315 wx = ax-static_cast<double>(i);
2316 wy = ay-static_cast<double>(j);
2317
2318 d2c = ad2c[i][j] * (1.-wx) * (1.-wy) +
2319 ad2c[i+1][j] * wx * (1.-wy) +
2320 ad2c[i][j+1] * (1.-wx) * wy +
2321 ad2c[i+1][j+1] * wx * wy;
2322
2323 } else d2c = 1.;
2324
2325 return d2c;
2326}
2327
2328
2329double DCCALShower_factory::cell_hyc( double dx, double dy )
2330{
2331 int i, j;
2332 double ax, ay, wx, wy;
2333 double cell_hyc;
2334
2335 ax = fabs(dx*100.);
2336 ay = fabs(dy*100.);
2337 i = static_cast<int>(ax);
2338 j = static_cast<int>(ay);
2339
2340 if( i < 499 && j < 499 && i >= 0 && j >= 0 ) {
2341
2342 wx = ax-static_cast<double>(i);
2343 wy = ay-static_cast<double>(j);
2344 //std::cout << "i " << i << " j " << j << " wx " << wx << " wy " << wy << std::endl;
2345 cell_hyc = acell[i][j] * (1.-wx) * (1.-wy) +
2346 acell[i+1][j] * wx * (1.-wy) +
2347 acell[i][j+1] * (1.-wx) * wy +
2348 acell[i+1][j+1] * wx * wy;
2349
2350 } else cell_hyc = 0.;
2351
2352 return cell_hyc;
2353}
2354
2355
2356
2357
2358
2359//==========================================================
2360//
2361// tgamma_hyc( int, vector<int>, vector<int>, int, vector<int>, double,
2362// double, double, double, double, double, double )
2363//
2364//==========================================================
2365
2366void DCCALShower_factory::tgamma_hyc( int nadc, vector<int> ia, vector<int> id,
2367 int nzero, vector<int> iaz, double &chisq, double &e1, double &x1, double &y1,
2368 double &e2, double &x2, double &y2 )
2369{
2370 //-------------- Local Declarations -------------//
2371
2372 int ix, iy;
2373 int dof;
2374
2375 double dx, dy;
2376 double dxy;
2377 double dxc, dyc;
2378 double dx0, dy0;
2379 double dx1, dy1;
2380 double dx2, dy2;
2381 double u, r, rsq, rsq2;
2382 double epsc, eps0, eps1, eps2;
2383 double stepmin, epsmax;
2384 double delch;
2385 double step;
2386 double cosi, scal;
2387 double chisq2, chisqc;
2388 double dchi, dchida, dchi0;
2389 double a1, a2;
2390 double ex;
2391 double e1c, x1c, y1c;
2392 double e2c, x2c, y2c;
2393 double gr, gre, grx, gry;
2394 double grc;
2395 double grec, grxc, gryc;
2396 double gx1, gy1;
2397 double gx2, gy2;
2398 double e0, x0, y0;
2399 double xx, yy, yx;
2400
2401 double f1c, f2c, f1x, f2x, f1y, f2y;
2402 double chisqt, chisqt0, chisqt1, chisqt2;
2403 double chisqtx1, chisqtx2, chisqty1, chisqty2;
2404 double dchidax1, dchidax2, dchiday1, dchiday2;
2405
2406 stepmin = 0.5;
2407 epsmax = 0.9999;
2408 delch = 10.;
2409
2410 //-------------- Event Analysis Code -------------//
2411
2412 yx = 0.;
2413 grx = 0.; gry = 0.;
2414 gre = 0.; gr = 0.;
2415 dx0 = 0.; dy0 = 0.;
2416 eps0 = 0.;
2417
2418 mom2_pht( nadc, ia, id, nzero, iaz, e0, x0, y0, xx, yy, yx );
2419
2420 e2 = 0.;
2421 x2 = 0.;
2422 y2 = 0.;
2423
2424 if( nadc <= 0 ) return;
2425
2426 // choosing of the starting point
2427
2428 dxy = xx - yy;
2429 rsq2 = dxy*dxy + 4.*yx*yx;
2430 if( rsq2 < 1.e-20 ) rsq2 = 1.e-20;
2431 rsq = sqrt(rsq2);
2432 dxc = -sqrt((rsq+dxy)*2.);
2433 dyc = sqrt((rsq-dxy)*2.);
2434 if( yx >= 0. ) dyc = -dyc;
2435 r = sqrt(dxc*dxc + dyc*dyc);
2436 epsc = 0.;
2437 for( int ii = 0; ii < nadc; ii++ ) {
2438 ix = ia[ii]/100;
2439 iy = ia[ii] - ix*100;
2440 dx = static_cast<double>(ix) - x0;
2441 dy = static_cast<double>(iy) - y0;
2442 u = dx*dxc/r + dy*dyc/r;
2443 epsc = epsc - 0.01*id[ii]*u*fabs(u);
2444 }
2445 epsc = epsc/(0.01*e0*rsq);
2446 if( epsc > 0.8 ) epsc = 0.8;
2447 if( epsc < -0.8 ) epsc = -0.8;
2448 dxc = dxc/sqrt(1.-(epsc*epsc));
2449 dyc = dyc/sqrt(1.-(epsc*epsc));
2450
2451
2452
2453 // start of iterations:
2454
2455 step = 0.1;
2456 cosi = 0.0;
2457 chisq2 = 1.e35;
2458
2459 for( int iter = 0; iter < 100; iter++ ) {
2460
2461 c3to5_pht( e0, x0, y0, epsc, dxc, dyc, e1c, x1c, y1c, e2c, x2c, y2c );
2462
2463 eps1 = (1. + epsc)/2.;
2464 eps2 = (1. - epsc)/2.;
2465 chisqc = 0.;
2466
2467 for( int ii = 0; ii < nadc+nzero; ii++ ) { // chi2 calculation
2468
2469 if( ii < nadc ) {
2470 ex = static_cast<double>(id[ii]);
2471 ix = ia[ii]/100;
2472 iy = ia[ii] - ix*100;
2473 } else {
2474 ex = 0.;
2475 ix = iaz[ii-nadc]/100;
2476 iy = iaz[ii-nadc] - ix*100;
2477 }
2478
2479 dx1 = x1c - static_cast<double>(ix);
2480 dy1 = y1c - static_cast<double>(iy);
2481 dx2 = x2c - static_cast<double>(ix);
2482 dy2 = y2c - static_cast<double>(iy);
2483
2484 f1c = cell_hyc( dx1, dy1 );
2485 f2c = cell_hyc( dx2, dy2 );
2486
2487 chisq2t_hyc( ex, e1c, dx1, dy1, e2c, dx2, dy2, f1c, f2c, chisqt );
2488 chisqc += chisqt;
2489
2490 }
2491
2492 if( chisqc >= chisq2 ) { // new step if no improvement
2493
2494 if( iter > 0 ) {
2495 dchi = chisqc - chisq2;
2496 dchi0 = gr*step;
2497 step = 0.5*step/sqrt(1. + dchi/dchi0);
2498 }
2499 step = 0.5*step;
2500
2501 } else { // calculate gradient
2502
2503 grec = 0.;
2504 grxc = 0.;
2505 gryc = 0.;
2506
2507 for( int ii = 0; ii < nadc+nzero; ii++ ) {
2508
2509 if( ii < nadc ) {
2510 ex = static_cast<double>(id[ii]);
2511 ix = ia[ii]/100;
2512 iy = ia[ii] - ix*100;
2513 } else {
2514 ex = 0.;
2515 ix = iaz[ii-nadc]/100;
2516 iy = iaz[ii-nadc] - ix*100;
2517 }
2518
2519 dx1 = x1c - static_cast<double>(ix);
2520 dy1 = y1c - static_cast<double>(iy);
2521 dx2 = x2c - static_cast<double>(ix);
2522 dy2 = y2c - static_cast<double>(iy);
2523
2524 f1c = cell_hyc( dx1, dy1 );
2525 f2c = cell_hyc( dx2, dy2 );
2526
2527 a1 = e1c*f1c;
2528 a2 = e2c*f2c;
2529 //a0 = a1 + a2;
2530
2531 chisq2t_hyc( ex, e1c, dx1, dy1, e2c, dx2, dy2, f1c, f2c, chisqt0 );
2532 chisq2t_hyc( ex, e1c+1., dx1, dy1, e2c, dx2, dy2, f1c, f2c, chisqt1 );
2533 chisq2t_hyc( ex, e1c, dx1, dy1, e2c+1., dx2, dy2, f1c, f2c, chisqt2 );
2534
2535 f1x = cell_hyc( dx1+0.05, dy1 );
2536 f2x = cell_hyc( dx2+0.05, dy2 );
2537 f1y = cell_hyc( dx1, dy1+0.05 );
2538 f2y = cell_hyc( dx2, dy2+0.05 );
2539
2540 chisq2t_hyc( ex, e1c, dx1+0.05, dy1, e2c, dx2, dy2, f1x, f2c, chisqtx1 );
2541 chisq2t_hyc( ex, e1c, dx1, dy1, e2c, dx2+0.05, dy2, f1c, f2x, chisqtx2 );
2542 chisq2t_hyc( ex, e1c, dx1, dy1+0.05, e2c, dx2, dy2, f1y, f2c, chisqty1 );
2543 chisq2t_hyc( ex, e1c, dx1, dy1, e2c, dx2, dy2+0.05, f1c, f2y, chisqty2 );
2544
2545 dchidax1 = 20.*(chisqtx1 - chisqt0);
2546 dchidax2 = 20.*(chisqtx2 - chisqt0);
2547 dchiday1 = 20.*(chisqty1 - chisqt0);
2548 dchiday2 = 20.*(chisqty2 - chisqt0);
2549 dchida = 0.5*(chisqt1 + chisqt2 - chisqt0);
2550
2551 gx1 = (e1c*f1x - a1)*dchidax1;
2552 gx2 = (e2c*f2x - a2)*dchidax2;
2553 gy1 = (e1c*f1y - a1)*dchiday1;
2554 gy2 = (e2c*f2y - a2)*dchiday2;
2555
2556 grec += dchida*(f1c-f2c)*e0 - ( (gx1+gx2)*dxc + (gy1+gy2)*dyc );
2557 grxc += gx1*eps2 - gx2*eps1;
2558 gryc += gy1*eps2 - gy2*eps1;
2559
2560 }
2561
2562 grc = sqrt( grec*grec + grxc*grxc + gryc*gryc );
2563 if( grc < 1.e-6 ) grc = 1.e-6;
2564 if( iter > 0 ) {
2565 cosi = ( gre*grec + grx*grxc + gry*gryc )/(gr*grc);
2566 scal = fabs((gr/grc) - cosi);
2567 if( scal < 0.1 ) scal = 0.1;
2568 step = step/scal;
2569 }
2570 chisq2 = chisqc;
2571 eps0 = epsc;
2572 dx0 = dxc;
2573 dy0 = dyc;
2574 gre = grec;
2575 grx = grxc;
2576 gry = gryc;
2577 gr = grc;
2578 }
2579 epsc = eps0 - step*gre/gr;
2580 while( fabs(epsc) > epsmax ) {
2581 step = step/2.;
2582 epsc = eps0 - step*gre/gr;
2583 }
2584 dxc = dx0 - step*grx/gr;
2585 dyc = dy0 - step*gry/gr;
2586 if( step*gr < stepmin ) break;
2587 }
2588
2589 if( (chisq*(nadc+nzero-2) - chisq2) < delch ) return;
2590 dof = nzero+nadc-5;
2591 if( dof < 1 ) dof = 1;
2592 chisq = chisq2/dof;
2593
2594 c3to5_pht( e0, x0, y0, eps0, dx0, dy0, e1, x1, y1, e2, x2, y2 );
2595
2596 return;
2597}
2598
2599
2600
2601
2602
2603//==========================================================
2604//
2605// mom2_pht( int, vector<int>, vector<int>, int, vector<int>,
2606// double, double, double, double, double, double )
2607//
2608//==========================================================
2609
2610void DCCALShower_factory::mom2_pht( int nadc, vector<int> ia, vector<int> id,
2611 int nzero, vector<int> iaz, double &a0, double &x0, double &y0,
2612 double &xx, double &yy, double &yx)
2613{
2614 //-------------- Local Declarations --------------//
2615
2616 int ix, iy;
2617 double dx, dy;
2618 double a;
2619 double corr;
2620
2621 //-------------- Event Analysis Code -------------//
2622
2623 a0 = 0.;
2624 x0 = 0.;
2625 y0 = 0.;
2626 xx = 0.;
2627 yy = 0.;
2628 yx = 0.;
2629
2630 if( nadc <= 0 ) return;
2631 for( int ii = 0; ii < nadc; ii++ ) {
2632 a = static_cast<double>(id[ii]);
2633 ix = ia[ii]/100;
2634 iy = ia[ii] - ix*100;
2635 a0 = a0 + a;
2636 x0 = x0 + a*static_cast<double>(ix);
2637 y0 = y0 + a*static_cast<double>(iy);
2638 }
2639 if( a0 <= 0. ) return;
2640 x0 = x0/a0;
2641 y0 = y0/a0;
2642
2643 for( int ii = 0; ii < nadc; ii++ ) {
2644 a = static_cast<double>(id[ii])/a0;
2645 ix = ia[ii]/100;
2646 iy = ia[ii] - ix*100;
2647 dx = static_cast<double>(ix) - x0;
2648 dy = static_cast<double>(iy) - y0;
2649 xx = xx + a*dx*dx;
2650 yy = yy + a*dy*dy;
2651 yx = yx + a*dx*dy;
2652 }
2653
2654 corr = 0.;
2655 for( int ii = 0; ii < nadc; ii++ ) {
2656 ix = ia[ii]/100;
2657 iy = ia[ii] - ix*100;
2658 dx = static_cast<double>(ix) - x0;
2659 dy = static_cast<double>(iy) - y0;
2660 corr = corr + cell_hyc( dx, dy );
2661 }
2662 if( COUNT_ZERO1 ) {
2663 for( int ii = 0; ii < nzero; ii++ ) {
2664 ix = iaz[ii]/100;
2665 iy = iaz[ii] - ix*100;
2666 dx = static_cast<double>(ix) - x0;
2667 dy = static_cast<double>(iy) - y0;
2668 corr = corr + cell_hyc( dx, dy );
2669 }
2670 }
2671
2672 corr = corr/1.006;
2673 if( corr < 0.8 ) {
2674 corr = 0.8;
2675 } else if( corr > 1. ) {
2676 corr = 1.0;
2677 }
2678 a0 = a0/corr;
2679
2680
2681 return;
2682}
2683
2684
2685
2686
2687
2688//==========================================================
2689//
2690// c3to5_pht( double, double, double, double, double, double,
2691// double, double, double, double, double, double )
2692//
2693//==========================================================
2694
2695void DCCALShower_factory::c3to5_pht( double e0, double x0, double y0, double eps,
2696 double dx, double dy, double &e1, double &x1, double &y1, double &e2,
2697 double &x2, double &y2 )
2698{
2699 e1 = e0*(1.+eps)/2.;
2700 e2 = e0 - e1;
2701 x1 = x0 + 0.5*dx*(1.-eps);
2702 y1 = y0 + 0.5*dy*(1.-eps);
2703 x2 = x0 - 0.5*dx*(1.+eps);
2704 y2 = y0 - 0.5*dy*(1.+eps);
2705
2706 return;
2707}
2708
2709
2710
2711
2712
2713//==========================================================
2714//
2715// chisq2t_hyc( double, double, double, double, double, double,
2716// double, double, double, double )
2717//
2718//==========================================================
2719
2720void DCCALShower_factory::chisq2t_hyc( double ecell, double e1, double dx1, double dy1,
2721 double e2, double dx2, double dy2, double f1, double f2, double &chisqt )
2722{
2723 double s;
2724 double p1, p2;
2725
2726 if( TEST_P1 ) {
2727 p1 = pow(0.0001*e1, 0.166);
2728 p2 = pow(0.0001*e2, 0.166);
2729 } else {
2730 p1 = 1.;
2731 p2 = 1.;
2732 }
2733
2734 if( e1 != 0. && e2 != 0. )
2735 s = e1*sigma2(dx1, dy1, f1, e1)/p1 + e2*sigma2(dx2, dy2, f2, e2)/p2;
2736 else if( e1 == 0. && e2 == 0. )
2737 s = 90000.;
2738 else if( e1 == 0. )
2739 s = e2*sigma2(dx2, dy2, f2, e2)/p2;
2740 else
2741 s = e1*sigma2(dx1, dy1, f1, e1)/p1;
2742
2743 chisqt = pow((e1*f1 + e2*f2 - ecell), 2.)/s;
2744
2745 return;
2746}
2747
2748
2749
2750
2751
2752
2753//==========================================================
2754//
2755// ucopy1( vector<int>, vector<int>, int, int )
2756//
2757//==========================================================
2758
2759void DCCALShower_factory::ucopy1( vector<int> &ia, vector<int> &iwork, int start, int length )
2760{
2761
2762 for( int ii = 0; ii < length; ii++ ) {
2763 iwork.push_back( ia[start+ii] );
2764 }
2765
2766
2767 return;
2768}
2769
2770
2771
2772//==========================================================
2773//
2774// ucopy2( vector<int>, int, int, int )
2775//
2776//==========================================================
2777
2778void DCCALShower_factory::ucopy2( vector<int> &ia, int start1, int start2, int length )
2779{
2780
2781 vector<int> work;
2782 for( int ii = 0; ii < length; ii++ ) {
2783 work.push_back( ia[start1+ii] );
2784 }
2785
2786 for( int ii = 0; ii < length; ii++ ) {
2787 ia[start2+ii] = work[ii];
2788 }
2789
2790
2791 return;
2792}
2793
2794
2795
2796
2797//==========================================================
2798//
2799// ucopy3( vector<int>, vector<int>, int, int )
2800//
2801//==========================================================
2802
2803void DCCALShower_factory::ucopy3( vector<int> &iwork, vector<int> &ia, int start, int length )
2804{
2805
2806 for( int ii = 0; ii < length; ii++ ) {
2807 ia[start+ii] = iwork[ii];
2808 }
2809
2810
2811 return;
2812}
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834

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

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

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

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