]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/STEERBase/AliMCEvent.cxx
shadowed argument corrected
[u/mrichter/AliRoot.git] / STEER / STEERBase / AliMCEvent.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 //-------------------------------------------------------------------------
19 //     Class for Kinematic Events
20 //     Author: Andreas Morsch, CERN
21 //-------------------------------------------------------------------------
22 #include <TArrow.h>
23 #include <TMarker.h>
24 #include <TH2F.h>
25 #include <TTree.h>
26 #include <TFile.h>
27 #include <TParticle.h>
28 #include <TClonesArray.h>
29 #include <TList.h>
30 #include <TArrayF.h>
31
32 #include "AliLog.h"
33 #include "AliMCEvent.h"
34 #include "AliMCVertex.h"
35 #include "AliStack.h"
36 #include "AliTrackReference.h"
37 #include "AliHeader.h"
38 #include "AliGenEventHeader.h"
39 #include "AliGenHijingEventHeader.h"
40 #include "AliGenCocktailEventHeader.h"
41
42
43 Int_t AliMCEvent::fgkBgLabelOffset(10000000);
44
45
46 AliMCEvent::AliMCEvent():
47     AliVEvent(),
48     fStack(0),
49     fMCParticles(0),
50     fMCParticleMap(0),
51     fHeader(new AliHeader()),
52     fAODMCHeader(0),
53     fTRBuffer(0),
54     fTrackReferences(new TClonesArray("AliTrackReference", 1000)),
55     fTreeTR(0),
56     fTmpTreeTR(0),
57     fTmpFileTR(0),
58     fNprimaries(-1),
59     fNparticles(-1),
60     fSubsidiaryEvents(0),
61     fPrimaryOffset(0),
62     fSecondaryOffset(0),
63     fExternal(0),
64     fVertex(0),
65     fNBG(-1)
66 {
67     // Default constructor
68 }
69
70 AliMCEvent::AliMCEvent(const AliMCEvent& mcEvnt) :
71     AliVEvent(mcEvnt),
72     fStack(mcEvnt.fStack),
73     fMCParticles(mcEvnt.fMCParticles),
74     fMCParticleMap(mcEvnt.fMCParticleMap),
75     fHeader(mcEvnt.fHeader),
76     fAODMCHeader(mcEvnt.fAODMCHeader),
77     fTRBuffer(mcEvnt.fTRBuffer),
78     fTrackReferences(mcEvnt.fTrackReferences),
79     fTreeTR(mcEvnt.fTreeTR),
80     fTmpTreeTR(mcEvnt.fTmpTreeTR),
81     fTmpFileTR(mcEvnt.fTmpFileTR),
82     fNprimaries(mcEvnt.fNprimaries),
83     fNparticles(mcEvnt.fNparticles),
84     fSubsidiaryEvents(0),
85     fPrimaryOffset(0),
86     fSecondaryOffset(0),
87     fExternal(0),
88     fVertex(mcEvnt.fVertex),
89     fNBG(mcEvnt.fNBG)
90
91 // Copy constructor
92 }
93
94
95 AliMCEvent& AliMCEvent::operator=(const AliMCEvent& mcEvnt)
96 {
97     // assignment operator
98     if (this!=&mcEvnt) { 
99         AliVEvent::operator=(mcEvnt); 
100     }
101   
102     return *this; 
103 }
104
105 void AliMCEvent::ConnectTreeE (TTree* tree)
106 {
107     // Connect the event header tree
108     tree->SetBranchAddress("Header", &fHeader);
109 }
110
111 void AliMCEvent::ConnectTreeK (TTree* tree)
112 {
113     // Connect Kinematics tree
114     fStack = fHeader->Stack();
115     fStack->ConnectTree(tree);
116     //
117     // Load the event
118     fStack->GetEvent();
119     
120     UpdateEventInformation();
121 }
122
123 void AliMCEvent::ConnectHeaderAndStack(AliHeader* header)
124 {
125   // fill MC event information from stack and header
126   
127   fHeader = header;
128   fStack = fHeader->Stack();
129
130   UpdateEventInformation();
131 }
132  
133 void AliMCEvent::UpdateEventInformation()
134 {
135     // bookkeeping for next event
136   
137     // Connect the kinematics tree to the stack
138     if (!fMCParticles) fMCParticles = new TClonesArray("AliMCParticle",1000);
139
140     // Initialize members
141     fNparticles = fStack->GetNtrack();
142     fNprimaries = fStack->GetNprimary();
143
144     Int_t iev  = fHeader->GetEvent();
145     Int_t ievr = fHeader->GetEventNrInRun();
146     AliDebug(1, Form("AliMCEvent# %5d %5d: Number of particles: %5d (all) %5d (primaries)\n", 
147                  iev, ievr, fNparticles, fNprimaries));
148  
149     // This is a cache for the TParticles converted to MCParticles on user request
150     if (fMCParticleMap) {
151         fMCParticleMap->Clear();
152         fMCParticles->Delete();
153         if (fNparticles>0) fMCParticleMap->Expand(fNparticles);
154     }
155     else
156         fMCParticleMap = new TObjArray(fNparticles);
157 }
158
159 void AliMCEvent::ConnectTreeTR (TTree* tree)
160 {
161     // Connect the track reference tree
162     fTreeTR = tree;
163     
164     if (fTreeTR->GetBranch("AliRun")) {
165         if (fTmpFileTR) {
166             fTmpFileTR->Close();
167             delete fTmpFileTR;
168         }
169         // This is an old format with one branch per detector not in synch with TreeK
170         ReorderAndExpandTreeTR();
171     } else {
172         // New format 
173         fTreeTR->SetBranchAddress("TrackReferences", &fTRBuffer);
174     }
175 }
176
177 Int_t AliMCEvent::GetParticleAndTR(Int_t i, TParticle*& particle, TClonesArray*& trefs)
178 {
179     // Retrieve entry i
180     if (i < 0 || i >= fNparticles) {
181         AliWarning(Form("AliMCEventHandler::GetEntry: Index out of range"));
182         particle = 0;
183         trefs    = 0;
184         return (-1);
185     }
186     particle = fStack->Particle(i);
187     if (fTreeTR) {
188         fTreeTR->GetEntry(fStack->TreeKEntry(i));
189         trefs    = fTRBuffer;
190         return trefs->GetEntries();
191     } else {
192         trefs = 0;
193         return -1;
194     }
195 }
196
197
198 void AliMCEvent::Clean()
199 {
200     // Clean-up before new trees are connected
201     delete fStack; fStack = 0;
202
203     // Clear TR
204     if (fTRBuffer) {
205         fTRBuffer->Delete();
206         delete fTRBuffer;
207         fTRBuffer = 0;
208     }
209 }
210
211 #include <iostream>
212
213 void AliMCEvent::FinishEvent()
214 {
215   // Clean-up after event
216   //    
217     if (fStack) fStack->Reset(0);
218     fMCParticles->Delete();
219     
220     if (fMCParticleMap) 
221       fMCParticleMap->Clear();
222     if (fTRBuffer) {
223       fTRBuffer->Delete();
224     }
225     //    fTrackReferences->Delete();
226     fTrackReferences->Clear();
227     fNparticles = -1;
228     fNprimaries = -1;    
229     fStack      =  0;
230 //    fSubsidiaryEvents->Clear();
231     fSubsidiaryEvents = 0;
232     fNBG = -1;
233 }
234
235
236
237 void AliMCEvent::DrawCheck(Int_t i, Int_t search)
238 {
239     //
240     // Simple event display for debugging
241     if (!fTreeTR) {
242         AliWarning("No Track Reference information available");
243         return;
244     } 
245     
246     if (i > -1 && i < fNparticles) {
247         fTreeTR->GetEntry(fStack->TreeKEntry(i));
248     } else {
249         AliWarning("AliMCEvent::GetEntry: Index out of range");
250     }
251     
252     Int_t nh = fTRBuffer->GetEntries();
253     
254     
255     if (search) {
256         while(nh <= search && i < fNparticles - 1) {
257             i++;
258             fTreeTR->GetEntry(fStack->TreeKEntry(i));
259             nh =  fTRBuffer->GetEntries();
260         }
261         printf("Found Hits at %5d\n", i);
262     }
263     TParticle* particle = fStack->Particle(i);
264     
265     TH2F*    h = new TH2F("", "", 100, -500, 500, 100, -500, 500);
266     Float_t x0 = particle->Vx();
267     Float_t y0 = particle->Vy();
268
269     Float_t x1 = particle->Vx() + particle->Px() * 50.;
270     Float_t y1 = particle->Vy() + particle->Py() * 50.;
271     
272     TArrow*  a = new TArrow(x0, y0, x1, y1, 0.01);
273     h->Draw();
274     a->SetLineColor(2);
275     
276     a->Draw();
277     
278     for (Int_t ih = 0; ih < nh; ih++) {
279         AliTrackReference* ref = (AliTrackReference*) fTRBuffer->At(ih);
280         TMarker* m = new TMarker(ref->X(), ref->Y(), 20);
281         m->Draw();
282         m->SetMarkerSize(0.4);
283         
284     }
285 }
286
287
288 void AliMCEvent::ReorderAndExpandTreeTR()
289 {
290 //
291 //  Reorder and expand the track reference tree in order to match the kinematics tree.
292 //  Copy the information from different branches into one
293 //
294 //  TreeTR
295
296     fTmpFileTR = new TFile("TrackRefsTmp.root", "recreate");
297     fTmpTreeTR = new TTree("TreeTR", "TrackReferences");
298     if (!fTRBuffer)  fTRBuffer = new TClonesArray("AliTrackReference", 100);
299     fTmpTreeTR->Branch("TrackReferences", "TClonesArray", &fTRBuffer, 64000, 0);
300     
301
302 //
303 //  Activate the used branches only. Otherwisw we get a bad memory leak.
304     if (fTreeTR) {
305         fTreeTR->SetBranchStatus("*",        0);
306         fTreeTR->SetBranchStatus("AliRun.*", 1);
307         fTreeTR->SetBranchStatus("ITS.*",    1);
308         fTreeTR->SetBranchStatus("TPC.*",    1);
309         fTreeTR->SetBranchStatus("TRD.*",    1);
310         fTreeTR->SetBranchStatus("TOF.*",    1);
311         fTreeTR->SetBranchStatus("FRAME.*",  1);
312         fTreeTR->SetBranchStatus("MUON.*",   1);
313     }
314     
315 //
316 //  Connect the active branches
317     TClonesArray* trefs[7];
318     for (Int_t i = 0; i < 7; i++) trefs[i] = 0;
319     if (fTreeTR){
320         // make branch for central track references
321         if (fTreeTR->GetBranch("AliRun")) fTreeTR->SetBranchAddress("AliRun", &trefs[0]);
322         if (fTreeTR->GetBranch("ITS"))    fTreeTR->SetBranchAddress("ITS",    &trefs[1]);
323         if (fTreeTR->GetBranch("TPC"))    fTreeTR->SetBranchAddress("TPC",    &trefs[2]);
324         if (fTreeTR->GetBranch("TRD"))    fTreeTR->SetBranchAddress("TRD",    &trefs[3]);
325         if (fTreeTR->GetBranch("TOF"))    fTreeTR->SetBranchAddress("TOF",    &trefs[4]);
326         if (fTreeTR->GetBranch("FRAME"))  fTreeTR->SetBranchAddress("FRAME",  &trefs[5]);
327         if (fTreeTR->GetBranch("MUON"))   fTreeTR->SetBranchAddress("MUON",   &trefs[6]);
328     }
329
330     Int_t np = fStack->GetNprimary();
331     Int_t nt = fTreeTR->GetEntries();
332     
333     //
334     // Loop over tracks and find the secondaries with the help of the kine tree
335     Int_t ifills = 0;
336     Int_t it     = 0;
337     Int_t itlast = 0;
338     TParticle* part;
339
340     for (Int_t ip = np - 1; ip > -1; ip--) {
341         part = fStack->Particle(ip);
342 //      printf("Particle %5d %5d %5d %5d %5d %5d \n", 
343 //             ip, part->GetPdgCode(), part->GetFirstMother(), part->GetFirstDaughter(), 
344 //             part->GetLastDaughter(), part->TestBit(kTransportBit));
345
346         // Determine range of secondaries produced by this primary during transport     
347         Int_t dau1  = part->GetFirstDaughter();
348         if (dau1 < np) continue;  // This particle has no secondaries produced during transport
349         Int_t dau2  = -1;
350         if (dau1 > -1) {
351             Int_t inext = ip - 1;
352             while (dau2 < 0) {
353                 if (inext >= 0) {
354                     part = fStack->Particle(inext);
355                     dau2 =  part->GetFirstDaughter();
356                     if (dau2 == -1 || dau2 < np) {
357                         dau2 = -1;
358                     } else {
359                         dau2--;
360                     }
361                 } else {
362                     dau2 = fStack->GetNtrack() - 1;
363                 }
364                 inext--;
365             } // find upper bound
366         }  // dau2 < 0
367         
368
369 //      printf("Check (1) %5d %5d %5d %5d %5d \n", ip, np, it, dau1, dau2);
370 //
371 // Loop over reference hits and find secondary label
372 // First the tricky part: find the entry in treeTR than contains the hits or
373 // make sure that no hits exist.
374 //
375         Bool_t hasHits   = kFALSE;
376         Bool_t isOutside = kFALSE;
377
378         it = itlast;
379         while (!hasHits && !isOutside && it < nt) {
380             fTreeTR->GetEntry(it++);
381             for (Int_t ib = 0; ib < 7; ib++) {
382                 if (!trefs[ib]) continue;
383                 Int_t nh = trefs[ib]->GetEntries();
384                 for (Int_t ih = 0; ih < nh; ih++) {
385                     AliTrackReference* tr = (AliTrackReference*) trefs[ib]->At(ih);
386                     Int_t label = tr->Label();
387                     if (label >= dau1 && label <= dau2) {
388                         hasHits = kTRUE;
389                         itlast = it - 1;
390                         break;
391                     }
392                     if (label > dau2 || label < ip) {
393                         isOutside = kTRUE;
394                         itlast = it - 1;
395                         break;
396                     }
397                 } // hits
398                 if (hasHits || isOutside) break;
399             } // branches
400         } // entries
401
402         if (!hasHits) {
403             // Write empty entries
404             for (Int_t id = dau1; (id <= dau2); id++) {
405                 fTmpTreeTR->Fill();
406                 ifills++;
407             } 
408         } else {
409             // Collect all hits
410             fTreeTR->GetEntry(itlast);
411             for (Int_t id = dau1; (id <= dau2) && (dau1 > -1); id++) {
412                 for (Int_t ib = 0; ib < 7; ib++) {
413                     if (!trefs[ib]) continue;
414                     Int_t nh = trefs[ib]->GetEntries();
415                     for (Int_t ih = 0; ih < nh; ih++) {
416                         AliTrackReference* tr = (AliTrackReference*) trefs[ib]->At(ih);
417                         Int_t label = tr->Label();
418                         // Skip primaries
419                         if (label == ip) continue;
420                         if (label > dau2 || label < dau1) 
421                             printf("AliMCEventHandler::Track Reference Label out of range !: %5d %5d %5d %5d \n", 
422                                    itlast, label, dau1, dau2);
423                         if (label == id) {
424                             // secondary found
425                             tr->SetDetectorId(ib-1);
426                             Int_t nref =  fTRBuffer->GetEntriesFast();
427                             TClonesArray &lref = *fTRBuffer;
428                             new(lref[nref]) AliTrackReference(*tr);
429                         }
430                     } // hits
431                 } // branches
432                 fTmpTreeTR->Fill();
433                 fTRBuffer->Delete();
434                 ifills++;
435             } // daughters
436         } // has hits
437     } // tracks
438
439     //
440     // Now loop again and write the primaries
441     //
442     it = nt - 1;
443     for (Int_t ip = 0; ip < np; ip++) {
444         Int_t labmax = -1;
445         while (labmax < ip && it > -1) {
446             fTreeTR->GetEntry(it--);
447             for (Int_t ib = 0; ib < 7; ib++) {
448                 if (!trefs[ib]) continue;
449                 Int_t nh = trefs[ib]->GetEntries();
450                 // 
451                 // Loop over reference hits and find primary labels
452                 for (Int_t ih = 0; ih < nh; ih++) {
453                     AliTrackReference* tr = (AliTrackReference*)  trefs[ib]->At(ih);
454                     Int_t label = tr->Label();
455                     if (label < np && label > labmax) {
456                         labmax = label;
457                     }
458                     
459                     if (label == ip) {
460                         tr->SetDetectorId(ib-1);
461                         Int_t nref = fTRBuffer->GetEntriesFast();
462                         TClonesArray &lref = *fTRBuffer;
463                         new(lref[nref]) AliTrackReference(*tr);
464                     }
465                 } // hits
466             } // branches
467         } // entries
468         it++;
469         fTmpTreeTR->Fill();
470         fTRBuffer->Delete();
471         ifills++;
472     } // tracks
473     // Check
474
475
476     // Clean-up
477     delete fTreeTR; fTreeTR = 0;
478     
479     for (Int_t ib = 0; ib < 7; ib++) {
480         if (trefs[ib]) {
481             trefs[ib]->Clear();
482             delete trefs[ib];
483             trefs[ib] = 0;
484         }
485     }
486
487     if (ifills != fStack->GetNtrack()) 
488         printf("AliMCEvent:Number of entries in TreeTR (%5d) unequal to TreeK (%5d) \n", 
489                ifills, fStack->GetNtrack());
490
491     fTmpTreeTR->Write();
492     fTreeTR = fTmpTreeTR;
493 }
494
495 AliVParticle* AliMCEvent::GetTrack(Int_t i) const
496 {
497     // Get MC Particle i
498     //
499
500     if (fExternal) {
501        
502   
503         return ((AliVParticle*) (fMCParticles->At(i)));
504   
505     }
506     
507     //
508     // Check first if this explicitely accesses the subsidiary event
509     
510     if (i >= BgLabelOffset()) {
511         if (fSubsidiaryEvents) {
512             AliMCEvent* bgEvent = (AliMCEvent*) (fSubsidiaryEvents->At(1));
513             return (bgEvent->GetTrack(i - BgLabelOffset()));
514         } else {
515             return 0;
516         }
517     }
518     
519     //
520     AliMCParticle *mcParticle = 0;
521     TParticle     *particle   = 0;
522     TClonesArray  *trefs      = 0;
523     Int_t          ntref      = 0;
524     TObjArray     *rarray     = 0;
525
526
527
528     // Out of range check
529     if (i < 0 || i >= fNparticles) {
530         AliWarning(Form("AliMCEvent::GetEntry: Index out of range"));
531         mcParticle = 0;
532         return (mcParticle);
533     }
534
535     
536     if (fSubsidiaryEvents) {
537         AliMCEvent*   mc;
538         Int_t idx = FindIndexAndEvent(i, mc);
539         return (mc->GetTrack(idx));
540     } 
541
542     //
543     // First check If the MC Particle has been already cached
544     if(!fMCParticleMap->At(i)) {
545         // Get particle from the stack
546         particle   = fStack->Particle(i);
547         // Get track references from Tree TR
548         if (fTreeTR) {
549             fTreeTR->GetEntry(fStack->TreeKEntry(i));
550             trefs     = fTRBuffer;
551             ntref     = trefs->GetEntriesFast();
552             rarray    = new TObjArray(ntref);
553             Int_t nen = fTrackReferences->GetEntriesFast();
554             for (Int_t j = 0; j < ntref; j++) {
555                 // Save the track references in a TClonesArray
556                 AliTrackReference* ref = dynamic_cast<AliTrackReference*>((*fTRBuffer)[j]);
557                 // Save the pointer in a TRefArray
558                 if (ref) {
559                     new ((*fTrackReferences)[nen]) AliTrackReference(*ref);
560                     rarray->AddAt((*fTrackReferences)[nen], j);
561                     nen++;
562                 }
563             } // loop over track references for entry i
564         } // if TreeTR available
565         Int_t nentries = fMCParticles->GetEntriesFast();
566         mcParticle = new ((*fMCParticles)[nentries]) AliMCParticle(particle, rarray, i);
567         fMCParticleMap->AddAt(mcParticle, i);
568         if (mcParticle) {
569             TParticle* part = mcParticle->Particle();
570             Int_t imo  = part->GetFirstMother();
571             Int_t id1  = part->GetFirstDaughter();
572             Int_t id2  = part->GetLastDaughter();
573             if (fPrimaryOffset > 0 || fSecondaryOffset > 0) {
574                 // Remapping of the mother and daughter indices
575                 if (imo < fNprimaries) {
576                     mcParticle->SetMother(imo + fPrimaryOffset);
577                 } else {
578                     mcParticle->SetMother(imo + fSecondaryOffset - fNprimaries);
579                 }
580                 
581                 if (id1 < fNprimaries) {
582                     mcParticle->SetFirstDaughter(id1 + fPrimaryOffset);
583                     mcParticle->SetLastDaughter (id2 + fPrimaryOffset);
584                 } else {
585                     mcParticle->SetFirstDaughter(id1 + fSecondaryOffset - fNprimaries);
586                     mcParticle->SetLastDaughter (id2 + fSecondaryOffset - fNprimaries);
587                 }
588                 
589                 
590                 if (i > fNprimaries) {
591                     mcParticle->SetLabel(i + fPrimaryOffset);
592                 } else {
593                     mcParticle->SetLabel(i + fSecondaryOffset - fNprimaries);
594                 }
595             } else {
596                 mcParticle->SetFirstDaughter(id1);
597                 mcParticle->SetLastDaughter (id2);
598                 mcParticle->SetMother       (imo);
599             }
600         }
601     } else {
602         mcParticle = dynamic_cast<AliMCParticle*>(fMCParticleMap->At(i));
603     }
604
605     //Printf("mcParticleGetMother %d",mcParticle->GetMother());
606     return mcParticle;
607 }
608
609 AliGenEventHeader* AliMCEvent::GenEventHeader() const 
610 {
611   if (!fExternal) {
612     // ESD
613     return (fHeader->GenEventHeader());
614   } else {
615     // AOD
616     if (fAODMCHeader) {
617       TList * lh = fAODMCHeader->GetCocktailHeaders();
618       if (lh) {return ((AliGenEventHeader*) lh->At(0));}
619     }
620   }
621   return 0;
622 }
623
624
625 void AliMCEvent::AddSubsidiaryEvent(AliMCEvent* event) 
626 {
627     // Add a subsidiary event to the list; for example merged background event.
628     if (!fSubsidiaryEvents) {
629         TList* events = new TList();
630         events->Add(new AliMCEvent(*this));
631         fSubsidiaryEvents = events;
632     }
633     
634     fSubsidiaryEvents->Add(event);
635 }
636
637 AliGenEventHeader *AliMCEvent::FindHeader(Int_t ipart) {
638   //
639   // Get Header belonging to this track; 
640   // only works for primaries (i.e. particles coming from the Generator)
641   // Also sorts out the case of Cocktail event (get header of subevent in cocktail generetor header)  
642   //
643
644   AliMCEvent *event = this;
645
646   if (fSubsidiaryEvents) {
647     // Get pointer to subevent if needed
648     ipart = FindIndexAndEvent(ipart,event); 
649   }
650
651   AliGenEventHeader* header = event->GenEventHeader();
652   if (ipart >= header->NProduced()) {
653     AliWarning(Form("Not a primary -- returning 0 (idx %d, nPrimary %d)",ipart,header->NProduced()));
654     return 0;
655   }
656   AliGenCocktailEventHeader *coHeader = dynamic_cast<AliGenCocktailEventHeader*>(header);
657   if (coHeader) { // Cocktail event
658     TList* headerList = coHeader->GetHeaders();
659     TIter headIt(headerList);
660     Int_t nproduced = 0;
661     do { // Go trhough all headers and look for the correct one
662       header = (AliGenEventHeader*) headIt();
663       if (header) nproduced += header->NProduced();
664     } while (header && ipart >= nproduced);
665   }
666
667   return header;
668 }
669
670 Int_t AliMCEvent::FindIndexAndEvent(Int_t oldidx, AliMCEvent*& event) const
671 {
672     // Find the index and event in case of composed events like signal + background
673     TIter next(fSubsidiaryEvents);
674     next.Reset();
675      if (oldidx < fNprimaries) {
676         while((event = (AliMCEvent*)next())) {
677             if (oldidx < (event->GetPrimaryOffset() + event->GetNumberOfPrimaries())) break;
678         }
679         if (event) {
680             return (oldidx - event->GetPrimaryOffset());
681         } else {
682             return (-1);
683         }
684     } else {
685         while((event = (AliMCEvent*)next())) {
686             if (oldidx < (event->GetSecondaryOffset() + (event->GetNumberOfTracks() - event->GetNumberOfPrimaries()))) break;
687         }
688         if (event) {
689             return (oldidx - event->GetSecondaryOffset() + event->GetNumberOfPrimaries());
690         } else {
691             return (-1);
692         }
693     }
694 }
695
696 Int_t AliMCEvent::BgLabelToIndex(Int_t label)
697 {
698     // Convert a background label to an absolute index
699     if (fSubsidiaryEvents) {
700         AliMCEvent* bgEvent = (AliMCEvent*) (fSubsidiaryEvents->At(1));
701         label -= BgLabelOffset();
702         if (label < bgEvent->GetNumberOfPrimaries()) {
703             label += bgEvent->GetPrimaryOffset();
704         } else {
705             label += (bgEvent->GetSecondaryOffset() - fNprimaries);
706         }
707     }
708     return (label);
709 }
710
711
712 Bool_t AliMCEvent::IsPhysicalPrimary(Int_t i) const
713 {
714 //
715 // Delegate to subevent if necesarry 
716
717     
718     if (!fSubsidiaryEvents) {
719         return fStack->IsPhysicalPrimary(i);
720     } else {
721         AliMCEvent* evt = 0;
722         Int_t idx = FindIndexAndEvent(i, evt);
723         return (evt->IsPhysicalPrimary(idx));
724     }
725 }
726
727 Bool_t AliMCEvent::IsSecondaryFromWeakDecay(Int_t i)
728 {
729 //
730 // Delegate to subevent if necesarry 
731     if (!fSubsidiaryEvents) {
732         return fStack->IsSecondaryFromWeakDecay(i);
733     } else {
734         AliMCEvent* evt = 0;
735         Int_t idx = FindIndexAndEvent(i, evt);
736         return (evt->IsSecondaryFromWeakDecay(idx));
737     }
738 }
739
740 Bool_t AliMCEvent::IsSecondaryFromMaterial(Int_t i)
741 {
742 //
743 // Delegate to subevent if necesarry 
744     if (!fSubsidiaryEvents) {
745         return fStack->IsSecondaryFromMaterial(i);
746     } else {
747         AliMCEvent* evt = 0;
748         Int_t idx = FindIndexAndEvent(i, evt);
749         return (evt->IsSecondaryFromMaterial(idx));
750     }
751 }
752
753
754 void AliMCEvent::InitEvent()
755 {
756 //
757 // Initialize the subsidiary event structure
758     if (fSubsidiaryEvents) {
759         TIter next(fSubsidiaryEvents);
760         AliMCEvent* evt;
761         fNprimaries = 0;
762         fNparticles = 0;
763         
764         while((evt = (AliMCEvent*)next())) {
765             fNprimaries += evt->GetNumberOfPrimaries(); 
766             fNparticles += evt->GetNumberOfTracks();    
767         }
768         
769         Int_t ioffp = 0;
770         Int_t ioffs = fNprimaries;
771         next.Reset();
772         
773         while((evt = (AliMCEvent*)next())) {
774             evt->SetPrimaryOffset(ioffp);
775             evt->SetSecondaryOffset(ioffs);
776             ioffp += evt->GetNumberOfPrimaries();
777             ioffs += (evt->GetNumberOfTracks() - evt->GetNumberOfPrimaries());      
778         }
779     }
780 }
781
782 void AliMCEvent::PreReadAll()                              
783 {
784     // Preread the MC information
785     Int_t i;
786     // secondaries
787     for (i = fStack->GetNprimary(); i < fStack->GetNtrack(); i++) 
788     {
789         GetTrack(i);
790     }
791     // primaries
792     for (i = 0; i < fStack->GetNprimary(); i++) 
793     {
794         GetTrack(i);
795     }
796     AssignGeneratorIndex();
797 }
798
799 const AliVVertex * AliMCEvent::GetPrimaryVertex() const 
800 {
801     // Create a MCVertex object from the MCHeader information
802     TArrayF v;
803     GenEventHeader()->PrimaryVertex(v) ;
804     if (!fVertex) {
805         fVertex = new AliMCVertex(v[0], v[1], v[2]);
806     } else {
807         ((AliMCVertex*) fVertex)->SetPosition(v[0], v[1], v[2]);
808     }
809     return fVertex;
810 }
811
812 Bool_t AliMCEvent::IsFromBGEvent(Int_t index)
813 {
814     // Checks if a particle is from the background events
815     // Works for HIJING inside Cocktail
816     if (fNBG == -1) {
817         AliGenCocktailEventHeader* coHeader = 
818             dynamic_cast<AliGenCocktailEventHeader*> (GenEventHeader());
819         if (!coHeader) return (0);
820         TList* list = coHeader->GetHeaders();
821         AliGenHijingEventHeader* hijingH = dynamic_cast<AliGenHijingEventHeader*>(list->FindObject("Hijing"));
822         if (!hijingH) return (0);
823         fNBG = hijingH->NProduced();
824     }
825     
826     return (index < fNBG);
827 }
828
829
830     TList* AliMCEvent::GetCocktailList()
831     {
832       //gives the CocktailHeaders when reading ESDs/AODs (corresponding to fExteral=kFALSE/kTRUE)
833       //the AODMC header (and the aodmc array) is passed as an instance to MCEvent by the AliAODInputHandler
834       if(fExternal==kFALSE) { 
835         AliGenCocktailEventHeader* coHeader =dynamic_cast<AliGenCocktailEventHeader*> (GenEventHeader());
836         if(!coHeader) {
837           return 0;
838         } else {
839           return (coHeader->GetHeaders());
840         }
841       } else {
842         if(!fAODMCHeader) { 
843           return 0;
844         } else {
845           return (fAODMCHeader->GetCocktailHeaders());
846         }
847       }
848     }
849
850
851 TString AliMCEvent::GetGenerator(Int_t index)
852 {
853   Int_t nsumpart=fNprimaries;
854   TList* lh = GetCocktailList();
855   if(!lh){ TString noheader="nococktailheader";
856     return noheader;}
857   Int_t nh=lh->GetEntries();
858   for (Int_t i = nh-1; i >= 0; i--){
859     AliGenEventHeader* gh=(AliGenEventHeader*)lh->At(i);
860     TString genname=gh->GetName();
861     Int_t npart=gh->NProduced();
862     if (i == 0) npart = nsumpart;
863     if(index < nsumpart && index >= (nsumpart-npart)) return genname;
864     nsumpart-=npart;
865   }
866   TString empty="";
867   return empty;
868 }
869
870 void AliMCEvent::AssignGeneratorIndex() {
871   //
872   // Assign the generator index to each particle
873   //
874   TList* list = GetCocktailList();
875   if (!list) {
876     return;
877   } else {
878     Int_t nh = list->GetEntries();
879     Int_t nsumpart = fNprimaries;
880     for(Int_t i = nh-1; i >= 0; i--){
881       AliGenEventHeader* gh = (AliGenEventHeader*)list->At(i);
882       Int_t npart = gh->NProduced();
883       if (i==0) {
884         if (npart != nsumpart) {
885           //      printf("Header inconsistent ! %5d %5d \n", npart, nsumpart);
886         }
887         npart = nsumpart;
888       }
889       //
890       // Loop over primary particles for generator i
891       for (Int_t j = nsumpart-1; j >= nsumpart-npart; j--) {
892         AliVParticle* part = GetTrack(j);
893         part->SetGeneratorIndex(i);
894         Int_t dmin = part->GetFirstDaughter();
895         Int_t dmax = part->GetLastDaughter();
896         if (dmin == -1) continue;
897         AssignGeneratorIndex(i, dmin, dmax);
898       } 
899       nsumpart -= npart;
900     }
901   }
902 }
903 void AliMCEvent::AssignGeneratorIndex(Int_t index, Int_t dmin, Int_t dmax) {
904   for (Int_t k = dmin; k <= dmax; k++) {
905     AliVParticle* dpart = GetTrack(k);
906     dpart->SetGeneratorIndex(index);
907     Int_t d1 = dpart->GetFirstDaughter();
908     Int_t d2 = dpart->GetLastDaughter();
909     if (d1 > -1) {
910       AssignGeneratorIndex(index, d1, d2);
911     }
912   }
913 }
914
915    Bool_t  AliMCEvent::GetCocktailGenerator(Int_t index,TString &nameGen){
916      //method that gives the generator for a given particle with label index (or that of the corresponding primary)
917      AliVParticle* mcpart0 = (AliVParticle*) (GetTrack(index));
918      if(!mcpart0){
919        printf("AliMCEvent-BREAK: No valid AliMCParticle at label %i\n",index);
920        return 0;
921      }
922      /*
923      Int_t ig = mcpart0->GetGeneratorIndex();
924      if (ig != -1) {
925        nameGen = ((AliGenEventHeader*)GetCocktailList()->At(ig))->GetName();
926        return 1;
927      }
928      */
929     nameGen=GetGenerator(index);
930     if(nameGen.Contains("nococktailheader") )return 0;
931     Int_t lab=index;
932
933     while(nameGen.IsWhitespace()){
934       
935       
936     AliVParticle* mcpart = (AliVParticle*) (GetTrack(lab));
937  
938      if(!mcpart){
939       printf("AliMCEvent-BREAK: No valid AliMCParticle at label %i\n",lab);
940       break;}
941      Int_t mother=0;
942      mother = mcpart->GetMother();
943    
944     if(mother<0){
945       printf("AliMCEvent - BREAK: Reached primary particle without valid mother\n");
946       break;
947     }
948       AliVParticle* mcmom = (AliVParticle*) (GetTrack(mother));
949       if(!mcmom){
950       printf("AliMCEvent-BREAK: No valid AliMCParticle mother at label %i\n",mother);
951        break;
952       }
953       lab=mother;
954    
955     nameGen=GetGenerator(mother);
956    }
957    
958    return 1;
959    }
960
961 void  AliMCEvent::SetParticleArray(TClonesArray* mcParticles) 
962   {
963     fMCParticles = mcParticles; 
964     fNparticles = fMCParticles->GetEntries(); 
965     fExternal = kTRUE; 
966     fNprimaries = 0;
967     for (Int_t i = 0; i < mcParticles->GetEntries(); i++) 
968       if  (((AliVParticle*) mcParticles->At(i))->IsPrimary()) fNprimaries++;
969     AssignGeneratorIndex();
970   }
971
972
973
974
975 ClassImp(AliMCEvent)