Initial check-in of the model classes
[u/mrichter/AliRoot.git] / PWG2 / FEMTOSCOPY / AliFemto / Analysis / AliFemtoAnalysis.cxx
1 /***************************************************************************
2  * Author: Mike Lisa, Ohio State, lisa@mps.ohio-state.edu
3  ***************************************************************************
4  *
5  * Description: part of STAR HBT Framework: AliFemtoMaker package
6  *      This is the Class for Analysis objects.  Each of the simultaneous
7  *      Analyses running should have one of these instantiated.  They link
8  *      into the Manager in an Analysis Collection.
9  *
10  ***************************************************************************
11  *
12  *
13  * Revision 1.23  2002/11/20 00:09:26  renault
14  * fill a new monitor with (hbtEvent,partCollection)
15  *
16  * Revision 1.22  2002/11/03 16:40:31  magestro
17  * Modified ProcessEvent(), added MakePairs() method, and implemented immediate event mixing
18  *
19  * Revision 1.21  2002/06/26 17:27:09  lisa
20  * fixed small bug in AliFemtoAnalysis associated with the new feature to require ParticleCollections to have some minimum number of particles
21  *
22  * Revision 1.20  2002/06/22 17:53:31  lisa
23  * implemented switch to allow user to require minimum number of particles in First and Second ParticleCollections - default value is zero so if user does not Set this value then behaviour is like before
24  *
25  * Revision 1.19  2001/11/06 20:20:53  laue
26  * Order of event-mixing fixed.
27  *
28  * Revision 1.18  2001/05/25 23:23:59  lisa
29  * Added in AliFemtoKink stuff
30  *
31  * Revision 1.17  2001/04/05 21:57:45  laue
32  * current pico-event becomes a member of the analysis (fPicoEvent) and gets
33  * an access-function (CurrentPicoEvent)
34  *
35  * Revision 1.15  2000/09/13 18:09:09  laue
36  * Bux fix: Delete track cut only once for identical particle hbt
37  *
38  * Revision 1.14  2000/08/31 22:31:30  laue
39  * AliFemtoAnalysis: output changed (a little bit less)
40  * AliFemtoEvent: new version, members for reference mult added
41  * AliFemtoIOBinary: new IO for new AliFemtoEvent version
42  * AliFemtoTypes: TTree typedef to AliFemtoTTree added
43  * AliFemtoVertexAnalysis: overflow and underflow added
44  *
45  * Revision 1.13  2000/08/11 16:35:40  rcwells
46  * Added number of events processed to each HBT analysis
47  *
48  * Revision 1.12  2000/07/16 22:23:17  laue
49  * I forgot that we moved memberfunctions out of AliFemtoBaseAnalysis.
50  * So my previous check-ins didn't compile with the library.
51  * Now they do.
52  *
53  * Revision 1.11  2000/07/16 21:38:22  laue
54  * AliFemtoCoulomb.cxx AliFemtoSectoredAnalysis.cxx : updated for standalone version
55  * AliFemtoV0.cc AliFemtoV0.h : some cast to prevent compiling warnings
56  * AliFemtoParticle.cc AliFemtoParticle.h : pointers mTrack,mV0 initialized to 0
57  * AliFemtoIOBinary.cc : some printouts in #ifdef STHBTDEBUG
58  * AliFemtoEvent.cc : B-Field set to 0.25Tesla, we have to think about a better
59  *                 solution
60  *
61  * Revision 1.10  2000/07/06 18:45:51  laue
62  * Copy constructor fixed. It couldn't handle identicle particles.
63  *
64  * Revision 1.9  2000/04/13 20:20:22  laue
65  * Event mixing corrected. Now the first collection of the current event is
66  * mixed with the second collection from the mixing buffer _AND_ vice verse
67  *
68  * Revision 1.8  2000/03/23 23:00:01  laue
69  * AliFemtoAnalysis copy constructor now uses Clone() function of cuts
70  * AliFemtoTypes now has AliFemtoTF1 for fitting purposes
71  *
72  * Revision 1.7  2000/03/17 17:23:05  laue
73  * Roberts new three particle correlations implemented.
74  *
75  * Revision 1.6  2000/03/16 02:07:04  laue
76  * Copy constructor added to AliFemtoAnalysis (only known cuts, corrfctn).
77  *
78  * AliFemtoBinaryReader can now derive filename from StIOMaker and read a list
79  * of files.
80  *
81  * AliFemtoManager now holds a collection of AliFemtoEventWriters (multiple writes
82  * possible now)
83  *
84  * Revision 1.5  2000/02/13 17:17:12  laue
85  * Calls to the EventBegin() and EventEnd() functions implemented
86  * The actual analysis is moved from AliFemtoManager to AliFemtoAnalysis
87  *
88  * Revision 1.4  2000/01/25 17:35:16  laue
89  * I. In order to run the stand alone version of the AliFemtoMaker the following
90  * changes have been done:
91  * a) all ClassDefs and ClassImps have been put into #ifdef __ROOT__ statements
92  * b) unnecessary includes of StMaker.h have been removed
93  * c) the subdirectory AliFemtoMaker/doc/Make has been created including everything
94  * needed for the stand alone version
95  *
96  * II. To reduce the amount of compiler warning
97  * a) some variables have been type casted
98  * b) some destructors have been declared as virtual
99  *
100  * Revision 1.3  1999/10/04 15:38:53  lisa
101  * include Franks new accessor methods AliFemtoAnalysis::CorrFctn and AliFemtoManager::Analysis as well as McEvent example macro
102  *
103  * Revision 1.2  1999/07/06 22:33:22  lisa
104  * Adjusted all to work in pro and new - dev itself is broken
105  *
106  * Revision 1.1.1.1  1999/06/29 16:02:57  lisa
107  * Installation of AliFemtoMaker
108  *
109  **************************************************************************/
110
111 #include "Analysis/AliFemtoAnalysis.h"
112 #include "Base/AliFemtoTrackCut.h"
113 #include "Base/AliFemtoV0Cut.h"
114 #include "Base/AliFemtoKinkCut.h"
115 #include <string>
116
117
118 #ifdef __ROOT__ 
119 ClassImp(AliFemtoAnalysis)
120 #endif
121
122 AliFemtoEventCut*    copyTheCut(AliFemtoEventCut*);
123 AliFemtoParticleCut* copyTheCut(AliFemtoParticleCut*);
124 AliFemtoPairCut*     copyTheCut(AliFemtoPairCut*);
125 AliFemtoCorrFctn*    copyTheCorrFctn(AliFemtoCorrFctn*);
126
127 // this little function used to apply ParticleCuts (TrackCuts or V0Cuts) and fill ParticleCollections of picoEvent
128 //  it is called from AliFemtoAnalysis::ProcessEvent()
129 void FillHbtParticleCollection(AliFemtoParticleCut*         partCut,
130                                AliFemtoEvent*               hbtEvent,
131                                AliFemtoParticleCollection*  partCollection)
132 {
133   switch (partCut->Type()) {
134   case hbtTrack:       // cut is cutting on Tracks
135     {
136       AliFemtoTrackCut* pCut = (AliFemtoTrackCut*) partCut;
137       AliFemtoTrack* pParticle;
138       AliFemtoTrackIterator pIter;
139       AliFemtoTrackIterator startLoop = hbtEvent->TrackCollection()->begin();
140       AliFemtoTrackIterator endLoop   = hbtEvent->TrackCollection()->end();
141       for (pIter=startLoop;pIter!=endLoop;pIter++){
142         pParticle = *pIter;
143         bool tmpPassParticle = pCut->Pass(pParticle);
144         pCut->FillCutMonitor(pParticle, tmpPassParticle);
145         if (tmpPassParticle){   
146           AliFemtoParticle* particle = new AliFemtoParticle(pParticle,pCut->Mass());
147           partCollection->push_back(particle);
148         }
149       }
150       break;
151     }
152   case hbtV0:          // cut is cutting on V0s
153     {
154       AliFemtoV0Cut* pCut = (AliFemtoV0Cut*) partCut;
155       AliFemtoV0* pParticle;
156       AliFemtoV0Iterator pIter;
157       AliFemtoV0Iterator startLoop = hbtEvent->V0Collection()->begin();
158       AliFemtoV0Iterator endLoop   = hbtEvent->V0Collection()->end();
159       // this following "for" loop is identical to the one above, but because of scoping, I can's see how to avoid repitition...
160       for (pIter=startLoop;pIter!=endLoop;pIter++){
161         pParticle = *pIter; 
162         bool tmpPassV0 = pCut->Pass(pParticle);
163         pCut->FillCutMonitor(pParticle,tmpPassV0);
164         if (tmpPassV0){
165           AliFemtoParticle* particle = new AliFemtoParticle(pParticle,partCut->Mass());
166           partCollection->push_back(particle);
167         }
168       }
169       pCut->FillCutMonitor(hbtEvent,partCollection);// Gael 19/06/02
170       break;
171     }
172   case hbtKink:          // cut is cutting on Kinks  -- mal 25May2001
173     {
174       AliFemtoKinkCut* pCut = (AliFemtoKinkCut*) partCut;
175       AliFemtoKink* pParticle;
176       AliFemtoKinkIterator pIter;
177       AliFemtoKinkIterator startLoop = hbtEvent->KinkCollection()->begin();
178       AliFemtoKinkIterator endLoop   = hbtEvent->KinkCollection()->end();
179       // this following "for" loop is identical to the one above, but because of scoping, I can's see how to avoid repitition...
180       for (pIter=startLoop;pIter!=endLoop;pIter++){
181         pParticle = *pIter; 
182         bool tmpPass = pCut->Pass(pParticle);
183         pCut->FillCutMonitor(pParticle,tmpPass);
184         if (tmpPass){
185           AliFemtoParticle* particle = new AliFemtoParticle(pParticle,partCut->Mass());
186           partCollection->push_back(particle);
187         }
188       }
189       break;
190     }
191   default:
192     cout << "FillHbtParticleCollection function (in AliFemtoAnalysis.cxx) - undefined Particle Cut type!!! \n";
193   }
194 }
195 //____________________________
196 AliFemtoAnalysis::AliFemtoAnalysis() :
197   fPicoEventCollectionVectorHideAway(0), 
198   fPairCut(0),            
199   fCorrFctnCollection(0), 
200   fEventCut(0),           
201   fFirstParticleCut(0),   
202   fSecondParticleCut(0),  
203   fMixingBuffer(0),       
204   fPicoEvent(0),          
205   fNumEventsToMix(0),                     
206   fNeventsProcessed(0),                   
207   fMinSizePartCollection(0)
208 {
209   //  mControlSwitch     = 0;
210   fCorrFctnCollection = new AliFemtoCorrFctnCollection;
211   fMixingBuffer = new AliFemtoPicoEventCollection;
212 }
213 //____________________________
214
215 AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) : 
216   AliFemtoBaseAnalysis(),
217   fPicoEventCollectionVectorHideAway(0), 
218   fPairCut(0),            
219   fCorrFctnCollection(0), 
220   fEventCut(0),           
221   fFirstParticleCut(0),   
222   fSecondParticleCut(0),  
223   fMixingBuffer(0),       
224   fPicoEvent(0),          
225   fNumEventsToMix(0),                     
226   fNeventsProcessed(0),                   
227   fMinSizePartCollection(0)
228 {
229   //AliFemtoAnalysis();
230   fCorrFctnCollection = new AliFemtoCorrFctnCollection;
231   fMixingBuffer = new AliFemtoPicoEventCollection;
232
233   // find the right event cut
234   fEventCut = a.fEventCut->Clone();
235   // find the right first particle cut
236   fFirstParticleCut = a.fFirstParticleCut->Clone();
237   // find the right second particle cut
238   if (a.fFirstParticleCut==a.fSecondParticleCut) 
239     SetSecondParticleCut(fFirstParticleCut); // identical particle hbt
240   else
241   fSecondParticleCut = a.fSecondParticleCut->Clone();
242
243   fPairCut = a.fPairCut->Clone();
244   
245   if ( fEventCut ) {
246       SetEventCut(fEventCut); // this will set the myAnalysis pointer inside the cut
247       cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - event cut set " << endl;
248   }
249   if ( fFirstParticleCut ) {
250       SetFirstParticleCut(fFirstParticleCut); // this will set the myAnalysis pointer inside the cut
251       cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - first particle cut set " << endl;
252   }
253   if ( fSecondParticleCut ) {
254       SetSecondParticleCut(fSecondParticleCut); // this will set the myAnalysis pointer inside the cut
255       cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - second particle cut set " << endl;
256   }  if ( fPairCut ) {
257       SetPairCut(fPairCut); // this will set the myAnalysis pointer inside the cut
258       cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - pair cut set " << endl;
259   }
260
261   AliFemtoCorrFctnIterator iter;
262   for (iter=a.fCorrFctnCollection->begin(); iter!=a.fCorrFctnCollection->end();iter++){
263     cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - looking for correlation functions " << endl;
264     AliFemtoCorrFctn* fctn = (*iter)->Clone();
265     if (fctn) AddCorrFctn(fctn);
266     else cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - correlation function not found " << endl;
267   }
268
269   fNumEventsToMix = a.fNumEventsToMix;
270
271   fMinSizePartCollection = a.fMinSizePartCollection;  // minimum # particles in ParticleCollection
272
273   cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - analysis copied " << endl;
274
275 }
276 //____________________________
277 AliFemtoAnalysis::~AliFemtoAnalysis(){
278   cout << " AliFemtoAnalysis::~AliFemtoAnalysis()" << endl;
279   if (fEventCut) delete fEventCut; fEventCut=0;
280   if (fFirstParticleCut == fSecondParticleCut) fSecondParticleCut=0;
281   if (fFirstParticleCut)  delete fFirstParticleCut; fFirstParticleCut=0;
282   if (fSecondParticleCut) delete fSecondParticleCut; fSecondParticleCut=0;
283   if (fPairCut) delete fPairCut; fPairCut=0;
284   // now delete every CorrFunction in the Collection, and then the Collection itself
285   AliFemtoCorrFctnIterator iter;
286   for (iter=fCorrFctnCollection->begin(); iter!=fCorrFctnCollection->end();iter++){
287     delete *iter;
288   }
289   delete fCorrFctnCollection;
290   // now delete every PicoEvent in the EventMixingBuffer and then the Buffer itself
291   if (fMixingBuffer) {
292     AliFemtoPicoEventIterator piter;
293     for (piter=fMixingBuffer->begin();piter!=fMixingBuffer->end();piter++){
294       delete *piter;
295     }
296     delete fMixingBuffer;
297   }
298 }
299 //______________________
300 AliFemtoAnalysis& AliFemtoAnalysis::operator=(const AliFemtoAnalysis& aAna) 
301 {
302   if (this == &aAna)
303     return *this;
304
305   fCorrFctnCollection = new AliFemtoCorrFctnCollection;
306   fMixingBuffer = new AliFemtoPicoEventCollection;
307
308   // find the right event cut
309   fEventCut = aAna.fEventCut->Clone();
310   // find the right first particle cut
311   fFirstParticleCut = aAna.fFirstParticleCut->Clone();
312   // find the right second particle cut
313   if (aAna.fFirstParticleCut==aAna.fSecondParticleCut) 
314     SetSecondParticleCut(fFirstParticleCut); // identical particle hbt
315   else
316     fSecondParticleCut = aAna.fSecondParticleCut->Clone();
317
318   fPairCut = aAna.fPairCut->Clone();
319   
320   if ( fEventCut ) {
321       SetEventCut(fEventCut); // this will set the myAnalysis pointer inside the cut
322       cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - event cut set " << endl;
323   }
324   if ( fFirstParticleCut ) {
325       SetFirstParticleCut(fFirstParticleCut); // this will set the myAnalysis pointer inside the cut
326       cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - first particle cut set " << endl;
327   }
328   if ( fSecondParticleCut ) {
329       SetSecondParticleCut(fSecondParticleCut); // this will set the myAnalysis pointer inside the cut
330       cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - second particle cut set " << endl;
331   }  if ( fPairCut ) {
332       SetPairCut(fPairCut); // this will set the myAnalysis pointer inside the cut
333       cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - pair cut set " << endl;
334   }
335
336   AliFemtoCorrFctnIterator iter;
337   for (iter=aAna.fCorrFctnCollection->begin(); iter!=aAna.fCorrFctnCollection->end();iter++){
338     cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - looking for correlation functions " << endl;
339     AliFemtoCorrFctn* fctn = (*iter)->Clone();
340     if (fctn) AddCorrFctn(fctn);
341     else cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - correlation function not found " << endl;
342   }
343
344   fNumEventsToMix = aAna.fNumEventsToMix;
345
346   fMinSizePartCollection = aAna.fMinSizePartCollection;  // minimum # particles in ParticleCollection
347
348   cout << " AliFemtoAnalysis::AliFemtoAnalysis(const AliFemtoAnalysis& a) - analysis copied " << endl;
349
350   return *this;
351 }
352 //______________________
353 AliFemtoCorrFctn* AliFemtoAnalysis::CorrFctn(int n){  // return pointer to n-th correlation function
354   if ( n<0 || n > (int)fCorrFctnCollection->size() )
355     return NULL;
356   AliFemtoCorrFctnIterator iter=fCorrFctnCollection->begin();
357   for (int i=0; i<n ;i++){
358     iter++;
359   }
360   return *iter;
361 }
362 //____________________________
363 AliFemtoString AliFemtoAnalysis::Report()
364 {
365   cout << "AliFemtoAnalysis - constructing Report..."<<endl;
366   string temp = "-----------\nHbt Analysis Report:\n";
367   temp += "\nEvent Cuts:\n";
368   temp += fEventCut->Report();
369   temp += "\nParticle Cuts - First Particle:\n";
370   temp += fFirstParticleCut->Report();
371   temp += "\nParticle Cuts - Second Particle:\n";
372   temp += fSecondParticleCut->Report();
373   temp += "\nPair Cuts:\n";
374   temp += fPairCut->Report();
375   temp += "\nCorrelation Functions:\n";
376   AliFemtoCorrFctnIterator iter;
377   if ( fCorrFctnCollection->size()==0 ) {
378     cout << "AliFemtoAnalysis-Warning : no correlations functions in this analysis " << endl;
379   }
380   for (iter=fCorrFctnCollection->begin(); iter!=fCorrFctnCollection->end();iter++){
381     temp += (*iter)->Report();
382     temp += "\n";
383   }
384   temp += "-------------\n";
385   AliFemtoString returnThis=temp;
386   return returnThis;
387 }
388 //_________________________
389 void AliFemtoAnalysis::ProcessEvent(const AliFemtoEvent* hbtEvent) {
390   // Add event to processed events
391   fPicoEvent=0; // we will get a new pico event, if not prevent corr. fctn to access old pico event
392   AddEventProcessed();
393   // startup for EbyE 
394   EventBegin(hbtEvent);  
395   // event cut and event cut monitor
396   bool tmpPassEvent = fEventCut->Pass(hbtEvent);
397   fEventCut->FillCutMonitor(hbtEvent, tmpPassEvent);
398   if (tmpPassEvent) {
399     cout << "AliFemtoAnalysis::ProcessEvent() - Event has passed cut - build picoEvent from " <<
400       hbtEvent->TrackCollection()->size() << " tracks in TrackCollection" << endl;
401     // OK, analysis likes the event-- build a pico event from it, using tracks the analysis likes...
402     fPicoEvent = new AliFemtoPicoEvent; // this is what we will make pairs from and put in Mixing Buffer
403     // no memory leak. we will delete picoevents when they come out of the mixing buffer
404     FillHbtParticleCollection(fFirstParticleCut,(AliFemtoEvent*)hbtEvent,fPicoEvent->FirstParticleCollection());
405     if ( !(AnalyzeIdenticalParticles()) )
406       FillHbtParticleCollection(fSecondParticleCut,(AliFemtoEvent*)hbtEvent,fPicoEvent->SecondParticleCollection());
407     cout <<"AliFemtoAnalysis::ProcessEvent - #particles in First, Second Collections: " <<
408       fPicoEvent->FirstParticleCollection()->size() << " " <<
409       fPicoEvent->SecondParticleCollection()->size() << endl;
410     
411     // mal - implement a switch which allows only using events with ParticleCollections containing a minimum
412     // number of entries (jun2002)
413     if ((fPicoEvent->FirstParticleCollection()->size() >= fMinSizePartCollection )
414         && ( AnalyzeIdenticalParticles() || (fPicoEvent->SecondParticleCollection()->size() >= fMinSizePartCollection ))) {
415
416
417 //------------------------------------------------------------------------------
418 //   Temporary comment:
419 //      This whole section rewritten so that all pairs are built using the
420 //      same code... easier to read and manage, and MakePairs() can be called by
421 //      derived classes.  Also, the requirement of a full mixing buffer before
422 //      mixing is removed.
423 //                          Dan Magestro, 11/2002
424
425       //------ Make real pairs. If identical, make pairs for one collection ------//
426
427       if (AnalyzeIdenticalParticles()) {
428         MakePairs("real", fPicoEvent->FirstParticleCollection() );
429       }
430       else {
431         MakePairs("real", fPicoEvent->FirstParticleCollection(),
432                           fPicoEvent->SecondParticleCollection() );
433       }
434       cout << "AliFemtoAnalysis::ProcessEvent() - reals done ";
435
436       //---- Make pairs for mixed events, looping over events in mixingBuffer ----//
437
438       AliFemtoPicoEvent* storedEvent;
439       AliFemtoPicoEventIterator fPicoEventIter;
440       for (fPicoEventIter=MixingBuffer()->begin();fPicoEventIter!=MixingBuffer()->end();fPicoEventIter++){
441         storedEvent = *fPicoEventIter;
442         if (AnalyzeIdenticalParticles()) {
443           MakePairs("mixed",fPicoEvent->FirstParticleCollection(),
444                             storedEvent->FirstParticleCollection() );
445         }
446         else {
447           MakePairs("mixed",fPicoEvent->FirstParticleCollection(),
448                             storedEvent->SecondParticleCollection() );
449
450           MakePairs("mixed",storedEvent->FirstParticleCollection(),
451                             fPicoEvent->SecondParticleCollection() );
452         }
453       }
454       cout << " - mixed done   " << endl;
455
456       //--------- If mixing buffer is full, delete oldest event ---------//
457
458       if ( MixingBufferFull() ) {
459         delete MixingBuffer()->back();
460         MixingBuffer()->pop_back();
461       }
462
463       //-------- Add current event (fPicoEvent) to mixing buffer --------//
464
465       MixingBuffer()->push_front(fPicoEvent);
466
467
468 // Temporary comment: End of rewritten section... Dan Magestro, 11/2002
469 //------------------------------------------------------------------------------
470
471
472     }  // if ParticleCollections are big enough (mal jun2002)
473     else{
474       delete fPicoEvent;
475     }
476   }   // if currentEvent is accepted by currentAnalysis
477   EventEnd(hbtEvent);  // cleanup for EbyE 
478   //cout << "AliFemtoAnalysis::ProcessEvent() - return to caller ... " << endl;
479 }
480 //_________________________
481 void AliFemtoAnalysis::MakePairs(const char* typeIn, AliFemtoParticleCollection *partCollection1,
482                                             AliFemtoParticleCollection *partCollection2){
483 // Build pairs, check pair cuts, and call CFs' AddRealPair() or
484 // AddMixedPair() methods. If no second particle collection is
485 // specfied, make pairs within first particle collection.
486
487   string type = typeIn;
488
489   AliFemtoPair* ThePair = new AliFemtoPair;
490
491   AliFemtoCorrFctnIterator CorrFctnIter;
492
493   AliFemtoParticleIterator PartIter1, PartIter2;
494
495   AliFemtoParticleIterator StartOuterLoop = partCollection1->begin();  // always
496   AliFemtoParticleIterator EndOuterLoop   = partCollection1->end();    // will be one less if identical
497   AliFemtoParticleIterator StartInnerLoop;
498   AliFemtoParticleIterator EndInnerLoop;
499   if (partCollection2) {                        // Two collections:
500     StartInnerLoop = partCollection2->begin();  //   Full inner & outer loops
501     EndInnerLoop   = partCollection2->end();    //
502   }
503   else {                                        // One collection:
504     EndOuterLoop--;                             //   Outer loop goes to next-to-last particle
505     EndInnerLoop = partCollection1->end() ;     //   Inner loop goes to last particle
506   }
507   for (PartIter1=StartOuterLoop;PartIter1!=EndOuterLoop;PartIter1++) {
508     if (!partCollection2){
509       StartInnerLoop = PartIter1;
510       StartInnerLoop++;
511     }
512     ThePair->SetTrack1(*PartIter1);
513     for (PartIter2 = StartInnerLoop; PartIter2!=EndInnerLoop;PartIter2++) {
514       ThePair->SetTrack2(*PartIter2);
515
516       // The following lines have to be uncommented if you want pairCutMonitors
517       // they are not in for speed reasons
518       // bool tmpPassPair = fPairCut->Pass(ThePair);
519       // fPairCut->FillCutMonitor(ThePair, tmpPassPair);
520       // if ( tmpPassPair )
521
522       //---- If pair passes cut, loop over CF's and add pair to real/mixed ----//
523
524       if (fPairCut->Pass(ThePair)){
525         for (CorrFctnIter=fCorrFctnCollection->begin();
526              CorrFctnIter!=fCorrFctnCollection->end();CorrFctnIter++){
527           AliFemtoCorrFctn* CorrFctn = *CorrFctnIter;
528           if(type == "real")
529             CorrFctn->AddRealPair(ThePair);
530           else if(type == "mixed")
531             CorrFctn->AddMixedPair(ThePair);
532           else
533             cout << "Problem with pair type, type = " << type.c_str() << endl;
534         }
535       }
536
537     }    // loop over second particle
538
539   }      // loop over first particle
540
541   delete ThePair;
542
543 }
544 //_________________________
545 void AliFemtoAnalysis::EventBegin(const AliFemtoEvent* ev){
546   //cout << " AliFemtoAnalysis::EventBegin(const AliFemtoEvent* ev) " << endl;
547   fFirstParticleCut->EventBegin(ev);
548   fSecondParticleCut->EventBegin(ev);
549   fPairCut->EventBegin(ev);
550   for (AliFemtoCorrFctnIterator iter=fCorrFctnCollection->begin(); iter!=fCorrFctnCollection->end();iter++){
551     (*iter)->EventBegin(ev);
552   }
553 }
554 //_________________________
555 void AliFemtoAnalysis::EventEnd(const AliFemtoEvent* ev){
556   fFirstParticleCut->EventEnd(ev);
557   fSecondParticleCut->EventEnd(ev);
558   fPairCut->EventEnd(ev);
559   for (AliFemtoCorrFctnIterator iter=fCorrFctnCollection->begin(); iter!=fCorrFctnCollection->end();iter++){
560     (*iter)->EventEnd(ev);
561   }
562 }
563 //_________________________
564 void AliFemtoAnalysis::Finish(){
565   AliFemtoCorrFctnIterator iter;
566   for (iter=fCorrFctnCollection->begin(); iter!=fCorrFctnCollection->end();iter++){
567     (*iter)->Finish();
568   }
569 }
570 //_________________________
571 void AliFemtoAnalysis::AddEventProcessed() {
572   fNeventsProcessed++;
573 }