MpdFemtoAnalysis.cxx 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. //
  2. // An example of the most basic (concrete) analysis
  3. //
  4. // C++ headers
  5. #include <string>
  6. #include <iostream>
  7. #include <iterator>
  8. #include <numeric>
  9. #include <algorithm>
  10. #include <random>
  11. // MpdFemtoMaker headers
  12. // Base
  13. #include "MpdFemtoBaseTrackCut.h"
  14. #include "MpdFemtoBaseV0Cut.h"
  15. #include "MpdFemtoBaseXiCut.h"
  16. #include "MpdFemtoBaseKinkCut.h"
  17. // Infrastructure
  18. #include "MpdFemtoAnalysis.h"
  19. // ROOT headers
  20. #include "TObject.h"
  21. #include "TString.h"
  22. ClassImp(MpdFemtoAnalysis)
  23. MpdFemtoBaseEventCut* copyTheCut(MpdFemtoBaseEventCut*);
  24. MpdFemtoBaseParticleCut* copyTheCut(MpdFemtoBaseParticleCut*);
  25. MpdFemtoBasePairCut* copyTheCut(MpdFemtoBasePairCut*);
  26. MpdFemtoBaseCorrFctn* copyTheCorrFctn(MpdFemtoBaseCorrFctn*);
  27. /// Generalized particle collection filler function - called by
  28. /// FillParticleCollection()
  29. ///
  30. /// This function loops over the track_collection, calling the cut's Pass
  31. /// method on each track. If it passes, a new MpdFemtoParticle is constructed
  32. /// from the track's pointer (or more generally, the item returned by
  33. /// dereferencing the container's iterator) and the cut's expected mass.
  34. ///
  35. /// This templated function accepts a track cut, track collection, and an
  36. /// MpdFemtoParticleCollection (which points to the output) as input. The types
  37. /// of the tracks are determined by the template paramters, which should be
  38. /// automatically detected by argument inspection (you don't need to specify).
  39. ///
  40. /// The original function also specified the iterator type, but since all
  41. /// containers are standard STL containers, it now infers the type as
  42. /// TrackCollectionType::iterator. If the track collections change to some
  43. /// other type, it is recommended to add TrackCollectionIterType to the
  44. /// template list, and add the appropriate type to the function calls in
  45. /// FillParticleCollection.
  46. template <class TrackCollectionType, class TrackCutType>
  47. void doFillParticleCollection(TrackCutType *cut,
  48. TrackCollectionType *track_collection,
  49. MpdFemtoParticleCollection *output, char doReshuffle) {
  50. MpdFemtoParticleCollection* initPartCollection = new MpdFemtoParticleCollection();
  51. for (const auto &track : *track_collection) {
  52. const Bool_t track_passes = cut->pass(track);
  53. cut->fillCutMonitor(track, track_passes);
  54. if (track_passes) {
  55. if (doReshuffle == 2)
  56. initPartCollection->push_back(new MpdFemtoParticle(track, cut->mass()));
  57. else
  58. output->push_back(new MpdFemtoParticle(track, cut->mass()));
  59. } //if (track_passes)
  60. } //for (const auto &track : *track_collection)
  61. //reshuffling implementation by means of reshuffling initPartCollection iterators in vector iterColl
  62. if (initPartCollection && doReshuffle == 2) {
  63. unsigned int collectionSize = initPartCollection->size();
  64. std::vector<MpdFemtoParticleIterator>* iterColl = new std::vector<MpdFemtoParticleIterator>(collectionSize);
  65. std::iota(iterColl->begin(), iterColl->end(), initPartCollection->begin()); //fill iterColl by iterators
  66. // debug---->
  67. // unsigned int iterCollSize = iterColl->size();
  68. // if(collectionSize!=iterCollSize){
  69. // std::cout<<"[ERROR]: Size of particles collection and size of iterators for this collection are different"<<
  70. // "\nSomthing is wrong with function std::iota ..."<<std::endl;
  71. // initPartCollection->clear();
  72. // return;
  73. // }
  74. // <----debug
  75. // Random generator initialization
  76. std::random_device rd;
  77. // Random generator initialization
  78. std::mt19937 gen(rd());
  79. std::shuffle(iterColl->begin(), iterColl->end(), gen);
  80. // debug---->
  81. // iterCollSize = iterColl->size();
  82. // if(collectionSize!=iterCollSize){
  83. // std::cout<<"[ERROR]: Size of iterators vector is changed after reshuffling"<<
  84. // "\nSomthing is wrong with function std::reshuffle..."<<std::endl;
  85. // initPartCollection->clear();
  86. // return;
  87. // }
  88. // <----debug
  89. for (vector <MpdFemtoParticleIterator>::iterator i = iterColl->begin(); i != iterColl->end(); i++) {
  90. output->push_back((*(*i)));
  91. }
  92. // debug---->
  93. // unsigned int outputSize = output->size();
  94. // if(collectionSize!=outputSize){
  95. // std::cout<<"[ERROR]: Size of particles collection is changed\n"<<
  96. // "during convertion from iterators vector to result particles collection"<<std::endl;
  97. // initPartCollection->clear();
  98. // return;
  99. // }
  100. // <----debug
  101. // debug printing BEGIN
  102. // Let's check we don't lose any particle because of reshuffling process
  103. // WARNING: Plain and really slow realization! Uncomment for debugging only
  104. // Idea: at first we verify that resulting collection contains all poiners MpdFemtoParticle*
  105. // from initial collection.
  106. // If it's right reshuffling process is correct, if it's not we should check vector of
  107. // iterators that participate
  108. // in reshuffling: 1. vector should be filled correctly; 2. all iterators are in this
  109. // vector after reshuffling algorithm.
  110. // //Sizes of all collections have been already checked in code wrapped by "//debug---> //<---debug"
  111. // bool found=0;
  112. // unsigned int k=0, l=0;
  113. // std::cout<<"Reshuffling result:"<<std::endl;
  114. // for(MpdFemtoParticleIterator i = initPartCollection->begin(); i != initPartCollection->end(); i++){
  115. // found=0;
  116. // l=0;
  117. // for(MpdFemtoParticleIterator j = output->begin(); j != output->end(); j++){
  118. // if((*i)==(*j)){
  119. // std::cout<<k<<"-"<<l<<" ";
  120. // found=1;
  121. // break;
  122. // }
  123. // l++;
  124. // }//for(MpdFemtoParticleIterator j = output->begin(); j != output->end(); j++)
  125. // if(found==0){
  126. // std::cout<<"[ERROR]: "<<k<<" particle can't be found. Let's check inner processes...'"<<std::endl;
  127. // break;
  128. // }
  129. // k++;
  130. // }//for(MpdFemtoParticleIterator i = initPartCollection->begin(); i != initPartCollection->end(); i++)
  131. // std::cout<<std::endl;
  132. // if(found==0){
  133. // //Vector of iterators verification
  134. // k=0;
  135. // for(MpdFemtoParticleIterator i = initPartCollection->begin(); i != initPartCollection->end(); i++){
  136. // if((*i) != *(iterColl->at(k)) ){
  137. // std::cout<<"[ERROR]: Wrong filling of iterators vector. Broken at "<<k<<" particle"<<
  138. // "\nSomthing is wrong with function std::iota ..."<<std::endl;
  139. // initPartCollection->clear();
  140. // return;
  141. // }
  142. // k++;
  143. // }//for(unsigned int i=0; i<collectionSize;i++)
  144. // //If this point is reached it means some problems are in std::shuffle.
  145. // std::cout<<"[ERROR]: std::shuffle loses some particles.\nYou lose."<<std::endl;
  146. // }//if(found==0)
  147. // else{
  148. // std::cout<<"You win!\nReshuffling process is ok.\n"<<std::endl;
  149. // }
  150. // //debug printing END
  151. initPartCollection->clear();
  152. }//if(initPartCollection && doReshuffle==2)
  153. }
  154. /// This little function is used to apply ParticleCuts (TrackCuts or V0Cuts) and
  155. /// fill ParticleCollections from tacks in picoEvent. It is called from
  156. /// MpdFemtoAnalysis::processEvent().
  157. ///
  158. /// The actual loop implementation has been moved to the collection-generic
  159. /// doFillParticleCollection() function
  160. void fillHbtParticleCollection(MpdFemtoBaseParticleCut* partCut,
  161. MpdFemtoEvent* hbtEvent,
  162. MpdFemtoParticleCollection* partCollection, char doReshuffle) {
  163. // Selection of the particle types: Track, V0, Kink
  164. switch (partCut->type()) {
  165. case hbtTrack:
  166. // Cut is cutting on Tracks
  167. doFillParticleCollection((MpdFemtoBaseTrackCut*) partCut,
  168. hbtEvent->trackCollection(),
  169. partCollection, doReshuffle);
  170. break;
  171. case hbtV0:
  172. // Cut is cutting on V0s
  173. doFillParticleCollection((MpdFemtoBaseV0Cut*) partCut,
  174. hbtEvent->v0Collection(),
  175. partCollection, doReshuffle);
  176. break;
  177. case hbtXi:
  178. // Cut is cutting on Xis
  179. doFillParticleCollection((MpdFemtoBaseXiCut*) partCut,
  180. hbtEvent->xiCollection(),
  181. partCollection, doReshuffle);
  182. break;
  183. case hbtKink:
  184. // Cut is cutting on Kinks
  185. doFillParticleCollection((MpdFemtoBaseKinkCut*) partCut,
  186. hbtEvent->kinkCollection(),
  187. partCollection, doReshuffle);
  188. break;
  189. default:
  190. std::cout << "fillHbtParticleCollection function (in MpdFemtoAnalysis.cxx): "
  191. << "Undefined Particle Cut type!!!" << partCut->type() << std::endl;
  192. } //switch (partCut->Type())
  193. partCut->fillCutMonitor(hbtEvent, partCollection);
  194. }
  195. //_________________
  196. MpdFemtoAnalysis::MpdFemtoAnalysis() :
  197. mPicoEventCollectionVectorHideAway(nullptr),
  198. mPairCut(nullptr), mCorrFctnCollection(nullptr),
  199. mEventCut(nullptr), mFirstParticleCut(nullptr),
  200. mSecondParticleCut(nullptr), mMixingBuffer(nullptr),
  201. mPicoEvent(nullptr), mNumEventsToMix(0), mNeventsProcessed(0),
  202. mMinSizePartCollection(0), mReshuffle(1),
  203. mVerbose(false) {
  204. // Default constructor
  205. mCorrFctnCollection = new MpdFemtoCorrFctnCollection;
  206. mMixingBuffer = new MpdFemtoPicoEventCollection;
  207. }
  208. //_________________
  209. MpdFemtoAnalysis::MpdFemtoAnalysis(const MpdFemtoAnalysis& a) :
  210. MpdFemtoBaseAnalysis(),
  211. mPicoEventCollectionVectorHideAway(nullptr),
  212. mPairCut(nullptr),
  213. mCorrFctnCollection(nullptr),
  214. mEventCut(nullptr),
  215. mFirstParticleCut(nullptr),
  216. mSecondParticleCut(nullptr),
  217. mMixingBuffer(nullptr),
  218. mPicoEvent(nullptr),
  219. mNumEventsToMix(a.mNumEventsToMix),
  220. mNeventsProcessed(0),
  221. mMinSizePartCollection(a.mMinSizePartCollection),
  222. mReshuffle(a.mReshuffle),
  223. mVerbose(a.mVerbose) {
  224. // Copy constructor
  225. const char msg_template[] = " MpdFemtoAnalysis::MpdFemtoAnalysis(const MpdFemtoAnalysis& a) - %s";
  226. const char warn_template[] = " [WARNING] MpdFemtoAnalysis::MpdFemtoAnalysis(const MpdFemtoAnalysis& a)] %s";
  227. mCorrFctnCollection = new MpdFemtoCorrFctnCollection;
  228. mMixingBuffer = new MpdFemtoPicoEventCollection;
  229. // Clone the event cut
  230. mEventCut = a.mEventCut->clone();
  231. if (mEventCut) {
  232. setEventCut(mEventCut);
  233. if (mVerbose) {
  234. std::cout << TString::Format(msg_template, "Event cut set") << std::endl;
  235. } // if( mVerbose )
  236. } else {
  237. std::cerr << Form(warn_template, "Cannot clone event cut!") << std::endl;
  238. }
  239. // Clone the first particle cut
  240. mFirstParticleCut = a.mFirstParticleCut->clone();
  241. if (mFirstParticleCut) {
  242. setFirstParticleCut(mFirstParticleCut);
  243. if (mVerbose) {
  244. std::cout << TString::Format(msg_template, "First particle cut set") << std::endl;
  245. } // if( mVerbose )
  246. } else {
  247. std::cerr << TString::Format(warn_template, "Cannot clone first particle cut!") << std::endl;
  248. }
  249. // Clone the second particle cut (if it exists)
  250. mSecondParticleCut = ((a.mFirstParticleCut == a.mSecondParticleCut) ?
  251. mFirstParticleCut : a.mSecondParticleCut);
  252. if (mSecondParticleCut) {
  253. setSecondParticleCut(mSecondParticleCut);
  254. if (mVerbose) {
  255. std::cout << TString::Format(msg_template, "Second particle cut set") << std::endl;
  256. } // if( mVerbose )
  257. } else {
  258. std::cerr << TString::Format(warn_template, "Cannot clone second particle cut!") << std::endl;
  259. }
  260. // Clone the pair cut
  261. mPairCut = a.mPairCut->clone();
  262. if (mPairCut) {
  263. setPairCut(mPairCut);
  264. if (mVerbose) {
  265. std::cout << TString::Format(msg_template, "Pair cut set") << std::endl;
  266. } // if( mVerbose )
  267. } else {
  268. std::cerr << TString::Format(warn_template, "Cannot clone pair cut!") << std::endl;
  269. }
  270. MpdFemtoCorrFctnIterator iter;
  271. for (iter = a.mCorrFctnCollection->begin();
  272. iter != a.mCorrFctnCollection->end(); iter++) {
  273. if (mVerbose) {
  274. std::cout << TString::Format(msg_template, "looking for correlation functions") << std::endl;
  275. } // if( mVerbose )
  276. MpdFemtoBaseCorrFctn* fctn = (*iter)->clone();
  277. if (fctn) {
  278. addCorrFctn(fctn);
  279. } else {
  280. std::cout << TString::Format(msg_template, "correlation function not found") << std::endl;
  281. }
  282. }
  283. if (mVerbose) {
  284. std::cout << TString::Format(msg_template, "Analysis copied") << std::endl;
  285. }
  286. }
  287. //_________________
  288. MpdFemtoAnalysis& MpdFemtoAnalysis::operator=(const MpdFemtoAnalysis& ana) {
  289. // Assignment operator
  290. if (this != &ana) {
  291. const char warn_template[] = "MpdFemtoAnalysis& MpdFemtoAnalysis::operator=(const MpdFemtoAnalysis& ana) : %s";
  292. // Clear second particle cut to avoid double delete
  293. if (mFirstParticleCut == mSecondParticleCut) {
  294. mSecondParticleCut = nullptr;
  295. }
  296. if (mEventCut) delete mEventCut;
  297. if (mPairCut) delete mPairCut;
  298. if (mFirstParticleCut) delete mFirstParticleCut;
  299. if (mSecondParticleCut) delete mSecondParticleCut;
  300. // Clear correlation functions
  301. if (mCorrFctnCollection) {
  302. for (MpdFemtoCorrFctnIterator iIter = mCorrFctnCollection->begin();
  303. iIter != mCorrFctnCollection->end(); iIter++) {
  304. delete *iIter;
  305. }
  306. mCorrFctnCollection->clear();
  307. }//if (mCorrFctnCollection)
  308. else {
  309. std::cerr << TString::Format(warn_template, "mCorrFctnCollection is a nullptr") << std::endl;
  310. mCorrFctnCollection = new MpdFemtoCorrFctnCollection;
  311. }
  312. // Clear mixing buffer
  313. if (mMixingBuffer) {
  314. for (MpdFemtoPicoEventIterator iIter = mMixingBuffer->begin();
  315. iIter != mMixingBuffer->end(); iIter++) {
  316. delete *iIter;
  317. }
  318. mMixingBuffer->clear();
  319. }//if (mMixingBuffer)
  320. else {
  321. std::cerr << TString::Format(warn_template, "mMixingBuffer is a nullptr") << std::endl;
  322. mMixingBuffer = new MpdFemtoPicoEventCollection;
  323. }
  324. // Copy objects
  325. mPairCut = ana.mPairCut->clone();
  326. mEventCut = ana.mEventCut->clone();
  327. mFirstParticleCut = ana.mFirstParticleCut->clone();
  328. mSecondParticleCut = ((ana.mFirstParticleCut == ana.mSecondParticleCut) ?
  329. mFirstParticleCut : ana.mSecondParticleCut->clone());
  330. // Check that cuts have just been coppied
  331. if (mEventCut) {
  332. setEventCut(mEventCut);
  333. } else {
  334. std::cerr << TString::Format(warn_template, "Could not copy the event cut") << std::endl;
  335. }
  336. if (mPairCut) {
  337. setPairCut(mPairCut);
  338. } else {
  339. std::cerr << TString::Format(warn_template, "Could not copy the pair cut") << std::endl;
  340. }
  341. if (mFirstParticleCut) {
  342. setFirstParticleCut(mFirstParticleCut);
  343. } else {
  344. std::cerr << TString::Format(warn_template, "Could not copy the first particle cut") << std::endl;
  345. }
  346. if (mSecondParticleCut) {
  347. setSecondParticleCut(mSecondParticleCut);
  348. } else {
  349. std::cerr << TString::Format(warn_template, "Could not copy the second particle cut") << std::endl;
  350. }
  351. // Copy correlation functions
  352. for (auto &cf : *ana.mCorrFctnCollection) {
  353. MpdFemtoBaseCorrFctn *fctn = cf->clone();
  354. if (fctn) {
  355. addCorrFctn(fctn);
  356. }
  357. }
  358. // Copy some numbers
  359. mNumEventsToMix = ana.mNumEventsToMix;
  360. mMinSizePartCollection = ana.mMinSizePartCollection;
  361. mReshuffle = ana.mReshuffle;
  362. mVerbose = ana.mVerbose;
  363. } //if ( this != &ana )
  364. return *this;
  365. }
  366. //_________________
  367. MpdFemtoAnalysis::~MpdFemtoAnalysis() {
  368. std::cout << "MpdFemtoAnalysis::~MpdFemtoAnalysis()" << std::endl;
  369. // Delete event cut
  370. if (mEventCut) delete mEventCut;
  371. mEventCut = nullptr;
  372. // Double-delete protection
  373. if (mFirstParticleCut == mSecondParticleCut) {
  374. mSecondParticleCut = nullptr;
  375. }
  376. if (mFirstParticleCut) delete mFirstParticleCut;
  377. mFirstParticleCut = nullptr;
  378. if (mSecondParticleCut) delete mSecondParticleCut;
  379. mSecondParticleCut = nullptr;
  380. if (mPairCut) delete mPairCut;
  381. mPairCut = nullptr;
  382. // Now delete every CorrFunction in the Collection, and then the Collection itself
  383. if (mCorrFctnCollection) {
  384. MpdFemtoCorrFctnIterator iter;
  385. for (iter = mCorrFctnCollection->begin();
  386. iter != mCorrFctnCollection->end(); iter++) {
  387. delete *iter;
  388. }
  389. delete mCorrFctnCollection;
  390. } //if( mCorrFctnCollection )
  391. // Now delete every PicoEvent in the EventMixingBuffer and then the Buffer itself
  392. if (mMixingBuffer) {
  393. MpdFemtoPicoEventIterator piter;
  394. for (piter = mMixingBuffer->begin();
  395. piter != mMixingBuffer->end(); piter++) {
  396. delete *piter;
  397. }
  398. delete mMixingBuffer;
  399. } //if (mMixingBuffer)
  400. }
  401. //_________________
  402. MpdFemtoBaseCorrFctn* MpdFemtoAnalysis::corrFctn(int n) {
  403. // Return pointer to n-th correlation function
  404. if ((n < 0) || (static_cast<size_t> (n) > mCorrFctnCollection->size())) {
  405. return nullptr;
  406. }
  407. MpdFemtoCorrFctnIterator iter = mCorrFctnCollection->begin();
  408. for (int i = 0; i < n; i++) {
  409. iter++;
  410. }
  411. return *iter;
  412. }
  413. //_________________________
  414. MpdFemtoString MpdFemtoAnalysis::reshReport() {
  415. string temp = "\nParticles reshuffling: ";
  416. switch (MpdFemtoAnalysis::reshuffle()) {
  417. case 0:
  418. {
  419. temp += "OFF";
  420. break;
  421. }
  422. case 1:
  423. {
  424. temp += "ON, swapping particles in pairs\n";
  425. break;
  426. }
  427. case 2:
  428. {
  429. temp += "ON, Fisher-Yates algorithm for particle collection\n";
  430. break;
  431. }
  432. default:
  433. temp += "[ERROR] MpdFemtoAnalsysis::mReshuffle has invalid value\n";
  434. }
  435. MpdFemtoString returnThis = temp;
  436. return returnThis;
  437. }
  438. //_________________
  439. MpdFemtoString MpdFemtoAnalysis::report() {
  440. // Create a simple report from the analysis execution
  441. std::cout << "MpdFemtoAnalysis - constructing Report..."
  442. << std::endl;
  443. string temp = "-----------\nHbt Analysis Report:\n";
  444. temp += reshReport();
  445. temp += "\nEvent Cuts:\n";
  446. temp += mEventCut->report();
  447. temp += "\nParticle Cuts - First Particle:\n";
  448. temp += mFirstParticleCut->report();
  449. temp += "\nParticle Cuts - Second Particle:\n";
  450. temp += mSecondParticleCut->report();
  451. temp += "\nPair Cuts:\n";
  452. temp += mPairCut->report();
  453. temp += "\nCorrelation Functions:\n";
  454. MpdFemtoCorrFctnIterator iter;
  455. if (mCorrFctnCollection->size() == 0) {
  456. std::cout << "MpdFemtoAnalysis-Warning : no correlations functions in this analysis "
  457. << std::endl;
  458. }
  459. for (iter = mCorrFctnCollection->begin(); iter != mCorrFctnCollection->end(); iter++) {
  460. temp += (*iter)->report();
  461. temp += "\n";
  462. }
  463. temp += "-------------\n";
  464. MpdFemtoString returnThis = temp;
  465. return returnThis;
  466. }
  467. //_________________
  468. void MpdFemtoAnalysis::processEvent(const MpdFemtoEvent* hbtEvent) {
  469. // Add event to processed events
  470. // We will get a new pico event, if not prevent
  471. // correlation function to access old pico event
  472. mPicoEvent = nullptr;
  473. addEventProcessed();
  474. // Startup for EbyE
  475. eventBegin(hbtEvent);
  476. // Event cut and event cut monitor
  477. bool tmpPassEvent = mEventCut->pass(hbtEvent);
  478. if (!tmpPassEvent) {
  479. mEventCut->fillCutMonitor(hbtEvent, tmpPassEvent);
  480. // Cleanup for EbyE
  481. eventEnd(hbtEvent);
  482. return;
  483. }
  484. // Analysis likes the event -- build a pico event from it, using tracks the
  485. // analysis likes. This is what we will make pairs from and put in Mixing
  486. // Buffer.
  487. // No memory leak. We will delete picoevent when they come out
  488. // of the mixing buffer
  489. mPicoEvent = new MpdFemtoPicoEvent;
  490. MpdFemtoParticleCollection *collection1 = mPicoEvent->firstParticleCollection();
  491. MpdFemtoParticleCollection *collection2 = mPicoEvent->secondParticleCollection();
  492. // Sanity check that both collections exist
  493. if (collection1 == nullptr || collection2 == nullptr) {
  494. std::cout << "MpdFemtoAnalysis::processEvent - new PicoEvent is missing particle collections!"
  495. << std::endl;
  496. eventEnd(hbtEvent);
  497. delete mPicoEvent;
  498. return;
  499. }
  500. // Subroutine fills fPicoEvent'a FirstParticleCollection with tracks from
  501. // hbtEvent which pass mFirstParticleCut. Uses cut's "type()" to determine
  502. // which track collection to pull from hbtEvent.
  503. fillHbtParticleCollection(mFirstParticleCut, (MpdFemtoEvent*) hbtEvent,
  504. mPicoEvent->firstParticleCollection(), mReshuffle);
  505. // In case of non-identical particles
  506. if (!(analyzeIdenticalParticles())) {
  507. fillHbtParticleCollection(mSecondParticleCut, (MpdFemtoEvent*) hbtEvent,
  508. mPicoEvent->secondParticleCollection(), mReshuffle);
  509. }
  510. if (mVerbose) {
  511. std::cout << " MpdFemtoAnalysis::processEvent - #particles in First, Second Collections: "
  512. << mPicoEvent->firstParticleCollection()->size() << " "
  513. << mPicoEvent->secondParticleCollection()->size() << std::endl;
  514. } // if ( mVerbose )
  515. const unsigned int coll_1_size = collection1->size();
  516. const unsigned int coll_2_size = collection2->size();
  517. const bool coll_1_size_passes = coll_1_size >= mMinSizePartCollection;
  518. const bool coll_2_size_passes = analyzeIdenticalParticles() || (coll_2_size >= mMinSizePartCollection);
  519. tmpPassEvent = (tmpPassEvent && coll_1_size_passes && coll_2_size_passes);
  520. // Fill event cut monitor
  521. mEventCut->fillCutMonitor(hbtEvent, tmpPassEvent);
  522. // Stop here if event did not pass cuts
  523. if (!tmpPassEvent) {
  524. eventEnd(hbtEvent);
  525. delete mPicoEvent;
  526. return;
  527. }
  528. //------ Make real pairs. If identical, make pairs for one collection ------//
  529. if (analyzeIdenticalParticles()) {
  530. makePairs("real", mPicoEvent->firstParticleCollection());
  531. } else {
  532. makePairs("real", mPicoEvent->firstParticleCollection(),
  533. mPicoEvent->secondParticleCollection());
  534. }
  535. if (mVerbose) {
  536. std::cout << "MpdFemtoAnalysis::processEvent() - reals done ";
  537. }
  538. //---- Make pairs for mixed events, looping over events in mixingBuffer ----//
  539. MpdFemtoPicoEvent* storedEvent;
  540. MpdFemtoPicoEventIterator mPicoEventIter;
  541. for (mPicoEventIter = mixingBuffer()->begin();
  542. mPicoEventIter != mixingBuffer()->end(); mPicoEventIter++) {
  543. storedEvent = *mPicoEventIter;
  544. if (analyzeIdenticalParticles()) {
  545. makePairs("mixed", mPicoEvent->firstParticleCollection(),
  546. storedEvent->firstParticleCollection());
  547. } else {
  548. makePairs("mixed", mPicoEvent->firstParticleCollection(),
  549. storedEvent->secondParticleCollection());
  550. makePairs("mixed", storedEvent->firstParticleCollection(),
  551. mPicoEvent->secondParticleCollection());
  552. }
  553. } //for ( mPicoEventIter=MixingBuffer()->begin(); mPicoEventIter!=MixingBuffer()->end(); mPicoEventIter++)
  554. if (mVerbose) {
  555. std::cout << " - mixed done " << std::endl;
  556. } // if (mVerbose)
  557. //--------- If mixing buffer is full, delete oldest event ---------//
  558. if (mixingBufferFull()) {
  559. delete mixingBuffer()->back();
  560. mixingBuffer()->pop_back();
  561. }
  562. //-------- Add current event (mPicoEvent) to mixing buffer --------//
  563. mixingBuffer()->push_front(mPicoEvent);
  564. // Cleanup for EbyE
  565. eventEnd(hbtEvent);
  566. //std::cout << "MpdFemtoAnalysis::ProcessEvent() - return to caller ... " << std::endl;
  567. }
  568. //_________________________
  569. void MpdFemtoAnalysis::makePairs(const char* typeIn,
  570. MpdFemtoParticleCollection *partCollection1,
  571. MpdFemtoParticleCollection *partCollection2) {
  572. // Build pairs, check pair cuts, and call CFs' AddRealPair() or
  573. // AddMixedPair() methods. If no second particle collection is
  574. // specfied, make pairs within first particle collection.
  575. const string type = typeIn;
  576. bool swpart = mNeventsProcessed % 2;
  577. // Create the pair outside the loop
  578. MpdFemtoPair* ThePair = new MpdFemtoPair;
  579. MpdFemtoCorrFctnIterator CorrFctnIter;
  580. MpdFemtoParticleIterator PartIter1, PartIter2;
  581. // Setup iterator ranges
  582. //
  583. // The outer loop alway starts at beginning of particle collection 1.
  584. // * If we are iterating over both particle collections, then the loop simply
  585. // runs through both from beginning to end.
  586. // * If we are only iterating over one particle collection, the inner loop
  587. // loops over all particles between the outer iterator and the end of the
  588. // collection. The outer loop must skip the last entry of the list.
  589. MpdFemtoParticleIterator StartOuterLoop = partCollection1->begin();
  590. MpdFemtoParticleIterator EndOuterLoop = partCollection1->end();
  591. MpdFemtoParticleIterator StartInnerLoop;
  592. MpdFemtoParticleIterator EndInnerLoop;
  593. if (partCollection2) { // Two collections:
  594. StartInnerLoop = partCollection2->begin(); // Full inner & outer loops
  595. EndInnerLoop = partCollection2->end(); //
  596. } else { // One collection:
  597. EndOuterLoop--; // Outer loop goes to next-to-last particle
  598. EndInnerLoop = partCollection1->end(); // Inner loop goes to last particle
  599. }
  600. // Start the outer loop
  601. for (PartIter1 = StartOuterLoop; PartIter1 != EndOuterLoop; PartIter1++) {
  602. // If analyzing identical particles, start inner loop at the particle
  603. // after the current outer loop position, (loops until end)
  604. if (!partCollection2) {
  605. StartInnerLoop = PartIter1;
  606. StartInnerLoop++;
  607. }
  608. // If we have two collections - set the first track
  609. if (mReshuffle != 1 || partCollection2 != nullptr) {
  610. ThePair->setTrack1(*PartIter1);
  611. }
  612. // Start the inner loop
  613. for (PartIter2 = StartInnerLoop; PartIter2 != EndInnerLoop; PartIter2++) {
  614. //If we have two collections - only set the second track
  615. if (mReshuffle != 1 || partCollection2 != nullptr) {
  616. ThePair->setTrack2(*PartIter2);
  617. } else {
  618. // Swap between first and second particles to avoid biased ordering
  619. ThePair->setTrack1(swpart ? *PartIter2 : *PartIter1);
  620. ThePair->setTrack2(swpart ? *PartIter1 : *PartIter2);
  621. swpart = !swpart;
  622. }
  623. // Check if the pair passes the cut
  624. bool tmpPassPair = mPairCut->pass(ThePair);
  625. mPairCut->fillCutMonitor(ThePair, tmpPassPair);
  626. // If pair passes cut, loop over CF's and add pair to real/mixed
  627. if (tmpPassPair) {
  628. // Iterate over correlation functions
  629. for (CorrFctnIter = mCorrFctnCollection->begin();
  630. CorrFctnIter != mCorrFctnCollection->end(); CorrFctnIter++) {
  631. MpdFemtoBaseCorrFctn* CorrFctn = *CorrFctnIter;
  632. if (type == "real") {
  633. CorrFctn->addRealPair(ThePair);
  634. } else if (type == "mixed") {
  635. CorrFctn->addMixedPair(ThePair);
  636. } else {
  637. std::cout << "Problem with pair type, type = " << type.c_str() << std::endl;
  638. }
  639. } //for (CorrFctnIter=mCorrFctnCollection->begin() ...
  640. } //if (mPairCut->Pass(ThePair))
  641. } //for (PartIter2 = StartInnerLoop; PartIter2 != EndInnerLoop; PartIter2++)
  642. } //for ( PartIter1 = StartOuterLoop; PartIter1 != EndOuterLoop; PartIter1++)
  643. // We are done with the pair
  644. delete ThePair;
  645. }
  646. //_________________
  647. void MpdFemtoAnalysis::setReshuffle(unsigned int type) {
  648. if (type > 2) {
  649. std::cout << "[WARNING] MpdFemtoAnalsysis::setReshuffle -- Bad reshuffling value \n Resetting...\n";
  650. mReshuffle = 1;
  651. } else {
  652. if (type == 0) {
  653. mReshuffle = 0;
  654. return;
  655. }
  656. if (type == 1) {
  657. mReshuffle = 1;
  658. return;
  659. }
  660. if (type == 2) {
  661. mReshuffle = 2;
  662. return;
  663. }
  664. }
  665. }
  666. //_________________
  667. void MpdFemtoAnalysis::eventBegin(const MpdFemtoEvent* ev) {
  668. // Perform initialization operations at the beginning of the event processing
  669. //std::cout << " MpdFemtoAnalysis::EventBegin(const MpdFemtoEvent* ev) " << std::endl;
  670. mFirstParticleCut->eventBegin(ev);
  671. mSecondParticleCut->eventBegin(ev);
  672. mPairCut->eventBegin(ev);
  673. for (MpdFemtoCorrFctnIterator iter = mCorrFctnCollection->begin();
  674. iter != mCorrFctnCollection->end(); iter++) {
  675. (*iter)->eventBegin(ev);
  676. }
  677. }
  678. //_________________
  679. void MpdFemtoAnalysis::eventEnd(const MpdFemtoEvent* ev) {
  680. // Finish operations at the end of event processing
  681. mFirstParticleCut->eventEnd(ev);
  682. mSecondParticleCut->eventEnd(ev);
  683. mPairCut->eventEnd(ev);
  684. for (MpdFemtoCorrFctnIterator iter = mCorrFctnCollection->begin();
  685. iter != mCorrFctnCollection->end(); iter++) {
  686. (*iter)->eventEnd(ev);
  687. }
  688. }
  689. //_________________
  690. void MpdFemtoAnalysis::finish() {
  691. MpdFemtoCorrFctnIterator iter;
  692. for (iter = mCorrFctnCollection->begin();
  693. iter != mCorrFctnCollection->end(); iter++) {
  694. (*iter)->finish();
  695. }
  696. }
  697. //_________________
  698. void MpdFemtoAnalysis::addEventProcessed() {
  699. mNeventsProcessed++;
  700. }
  701. //_________________
  702. TList* MpdFemtoAnalysis::listSettings() {
  703. // Collect settings list
  704. const TString setting_prefix = "MpdFemtoAnalysis.";
  705. TList *tListSettings = new TList();
  706. TList *event_cut_settings = mEventCut->listSettings();
  707. if (event_cut_settings != nullptr) {
  708. TListIter next_event_setting(event_cut_settings);
  709. while (TObject * obj = next_event_setting()) {
  710. tListSettings->Add(new TObjString(setting_prefix + obj->GetName()));
  711. }
  712. delete event_cut_settings;
  713. } //if (event_cut_settings != nullptr)
  714. TList *p1_cut_settings = mFirstParticleCut->listSettings();
  715. if (p1_cut_settings != nullptr) {
  716. TListIter next_p1_setting(p1_cut_settings);
  717. while (TObject * obj = next_p1_setting()) {
  718. tListSettings->Add(new TObjString(setting_prefix + obj->GetName()));
  719. }
  720. delete p1_cut_settings;
  721. } //if (p1_cut_settings != nullptr)
  722. if (mSecondParticleCut != mFirstParticleCut) {
  723. TList *p2_cut_settings = mSecondParticleCut->listSettings();
  724. if (p2_cut_settings != nullptr) {
  725. TListIter next_p2_setting(p2_cut_settings);
  726. while (TObject * obj = next_p2_setting()) {
  727. tListSettings->Add(new TObjString(setting_prefix + obj->GetName()));
  728. }
  729. delete p2_cut_settings;
  730. }
  731. } //if (fSecondParticleCut != fFirstParticleCut)
  732. TList *pair_cut_settings = mPairCut->listSettings();
  733. if (pair_cut_settings != nullptr) {
  734. TListIter next_pair_setting(pair_cut_settings);
  735. while (TObject * obj = next_pair_setting()) {
  736. tListSettings->Add(new TObjString(setting_prefix + obj->GetName()));
  737. }
  738. delete pair_cut_settings;
  739. } //if (pair_cut_settings != nullptr)
  740. return tListSettings;
  741. }
  742. //_________________________
  743. TList* MpdFemtoAnalysis::getOutputList() {
  744. // Collect the list of output objects to be written
  745. TList *tOutputList = new TList();
  746. TList *p1Cut = mFirstParticleCut->getOutputList();
  747. TListIter nextp1(p1Cut);
  748. while (TObject * obj = nextp1.Next()) {
  749. tOutputList->Add(obj);
  750. }
  751. delete p1Cut;
  752. if (mSecondParticleCut != mFirstParticleCut) {
  753. TList *p2Cut = mSecondParticleCut->getOutputList();
  754. TIter nextp2(p2Cut);
  755. while (TObject * obj = nextp2()) {
  756. tOutputList->Add(obj);
  757. }
  758. delete p2Cut;
  759. } //if (fSecondParticleCut != fFirstParticleCut)
  760. TList *pairCut = mPairCut->getOutputList();
  761. TIter nextpair(pairCut);
  762. while (TObject * obj = nextpair()) {
  763. tOutputList->Add(obj);
  764. }
  765. delete pairCut;
  766. TList *eventCut = mEventCut->getOutputList();
  767. TIter nextevent(eventCut);
  768. while (TObject * obj = nextevent()) {
  769. tOutputList->Add(obj);
  770. }
  771. delete eventCut;
  772. for (auto &cf : *mCorrFctnCollection) {
  773. TList *tListCf = cf->getOutputList();
  774. TIter nextListCf(tListCf);
  775. while (TObject * obj = nextListCf()) {
  776. tOutputList->Add(obj);
  777. }
  778. delete tListCf;
  779. }
  780. return tOutputList;
  781. }