1 /**************************************************************************
2 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 //-------------------------------------------------------------------------
19 // Class for Kinematic Events
20 // Author: Andreas Morsch, CERN
21 //-------------------------------------------------------------------------
27 #include <TParticle.h>
28 #include <TClonesArray.h>
33 #include "AliMCEvent.h"
34 #include "AliMCVertex.h"
36 #include "AliTrackReference.h"
37 #include "AliHeader.h"
38 #include "AliGenEventHeader.h"
39 #include "AliGenHijingEventHeader.h"
40 #include "AliGenCocktailEventHeader.h"
43 Int_t AliMCEvent::fgkBgLabelOffset(10000000);
46 AliMCEvent::AliMCEvent():
51 fHeader(new AliHeader()),
54 fTrackReferences(new TClonesArray("AliTrackReference", 1000)),
67 // Default constructor
70 AliMCEvent::AliMCEvent(const AliMCEvent& 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),
88 fVertex(mcEvnt.fVertex),
95 AliMCEvent& AliMCEvent::operator=(const AliMCEvent& mcEvnt)
97 // assignment operator
99 AliVEvent::operator=(mcEvnt);
105 void AliMCEvent::ConnectTreeE (TTree* tree)
107 // Connect the event header tree
108 tree->SetBranchAddress("Header", &fHeader);
111 void AliMCEvent::ConnectTreeK (TTree* tree)
113 // Connect Kinematics tree
114 fStack = fHeader->Stack();
115 fStack->ConnectTree(tree);
120 UpdateEventInformation();
123 void AliMCEvent::ConnectHeaderAndStack(AliHeader* header)
125 // fill MC event information from stack and header
128 fStack = fHeader->Stack();
130 UpdateEventInformation();
133 void AliMCEvent::UpdateEventInformation()
135 // bookkeeping for next event
137 // Connect the kinematics tree to the stack
138 if (!fMCParticles) fMCParticles = new TClonesArray("AliMCParticle",1000);
140 // Initialize members
141 fNparticles = fStack->GetNtrack();
142 fNprimaries = fStack->GetNprimary();
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));
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);
156 fMCParticleMap = new TObjArray(fNparticles);
159 void AliMCEvent::ConnectTreeTR (TTree* tree)
161 // Connect the track reference tree
164 if (fTreeTR->GetBranch("AliRun")) {
169 // This is an old format with one branch per detector not in synch with TreeK
170 ReorderAndExpandTreeTR();
173 fTreeTR->SetBranchAddress("TrackReferences", &fTRBuffer);
177 Int_t AliMCEvent::GetParticleAndTR(Int_t i, TParticle*& particle, TClonesArray*& trefs)
180 if (i < 0 || i >= fNparticles) {
181 AliWarning(Form("AliMCEventHandler::GetEntry: Index out of range"));
186 particle = fStack->Particle(i);
188 fTreeTR->GetEntry(fStack->TreeKEntry(i));
190 return trefs->GetEntries();
198 void AliMCEvent::Clean()
200 // Clean-up before new trees are connected
201 delete fStack; fStack = 0;
213 void AliMCEvent::FinishEvent()
215 // Clean-up after event
217 if (fStack) fStack->Reset(0);
218 fMCParticles->Delete();
221 fMCParticleMap->Clear();
225 // fTrackReferences->Delete();
226 fTrackReferences->Clear();
230 // fSubsidiaryEvents->Clear();
231 fSubsidiaryEvents = 0;
237 void AliMCEvent::DrawCheck(Int_t i, Int_t search)
240 // Simple event display for debugging
242 AliWarning("No Track Reference information available");
246 if (i > -1 && i < fNparticles) {
247 fTreeTR->GetEntry(fStack->TreeKEntry(i));
249 AliWarning("AliMCEvent::GetEntry: Index out of range");
252 Int_t nh = fTRBuffer->GetEntries();
256 while(nh <= search && i < fNparticles - 1) {
258 fTreeTR->GetEntry(fStack->TreeKEntry(i));
259 nh = fTRBuffer->GetEntries();
261 printf("Found Hits at %5d\n", i);
263 TParticle* particle = fStack->Particle(i);
265 TH2F* h = new TH2F("", "", 100, -500, 500, 100, -500, 500);
266 Float_t x0 = particle->Vx();
267 Float_t y0 = particle->Vy();
269 Float_t x1 = particle->Vx() + particle->Px() * 50.;
270 Float_t y1 = particle->Vy() + particle->Py() * 50.;
272 TArrow* a = new TArrow(x0, y0, x1, y1, 0.01);
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);
282 m->SetMarkerSize(0.4);
288 void AliMCEvent::ReorderAndExpandTreeTR()
291 // Reorder and expand the track reference tree in order to match the kinematics tree.
292 // Copy the information from different branches into one
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);
303 // Activate the used branches only. Otherwisw we get a bad memory leak.
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);
316 // Connect the active branches
317 TClonesArray* trefs[7];
318 for (Int_t i = 0; i < 7; i++) trefs[i] = 0;
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]);
330 Int_t np = fStack->GetNprimary();
331 Int_t nt = fTreeTR->GetEntries();
334 // Loop over tracks and find the secondaries with the help of the kine tree
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));
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
351 Int_t inext = ip - 1;
354 part = fStack->Particle(inext);
355 dau2 = part->GetFirstDaughter();
356 if (dau2 == -1 || dau2 < np) {
362 dau2 = fStack->GetNtrack() - 1;
365 } // find upper bound
369 // printf("Check (1) %5d %5d %5d %5d %5d \n", ip, np, it, dau1, dau2);
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.
375 Bool_t hasHits = kFALSE;
376 Bool_t isOutside = kFALSE;
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) {
392 if (label > dau2 || label < ip) {
398 if (hasHits || isOutside) break;
403 // Write empty entries
404 for (Int_t id = dau1; (id <= dau2); id++) {
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();
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);
425 tr->SetDetectorId(ib-1);
426 Int_t nref = fTRBuffer->GetEntriesFast();
427 TClonesArray &lref = *fTRBuffer;
428 new(lref[nref]) AliTrackReference(*tr);
440 // Now loop again and write the primaries
443 for (Int_t ip = 0; ip < np; ip++) {
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();
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) {
460 tr->SetDetectorId(ib-1);
461 Int_t nref = fTRBuffer->GetEntriesFast();
462 TClonesArray &lref = *fTRBuffer;
463 new(lref[nref]) AliTrackReference(*tr);
477 delete fTreeTR; fTreeTR = 0;
479 for (Int_t ib = 0; ib < 7; ib++) {
487 if (ifills != fStack->GetNtrack())
488 printf("AliMCEvent:Number of entries in TreeTR (%5d) unequal to TreeK (%5d) \n",
489 ifills, fStack->GetNtrack());
492 fTreeTR = fTmpTreeTR;
495 AliVParticle* AliMCEvent::GetTrack(Int_t i) const
501 return ((AliVParticle*) (fMCParticles->At(i)));
505 // Check first if this explicitely accesses the subsidiary event
507 if (i >= BgLabelOffset()) {
508 if (fSubsidiaryEvents) {
509 AliMCEvent* bgEvent = (AliMCEvent*) (fSubsidiaryEvents->At(1));
510 return (bgEvent->GetTrack(i - BgLabelOffset()));
517 AliMCParticle *mcParticle = 0;
518 TParticle *particle = 0;
519 TClonesArray *trefs = 0;
521 TObjArray *rarray = 0;
525 // Out of range check
526 if (i < 0 || i >= fNparticles) {
527 AliWarning(Form("AliMCEvent::GetEntry: Index out of range"));
533 if (fSubsidiaryEvents) {
535 Int_t idx = FindIndexAndEvent(i, mc);
536 return (mc->GetTrack(idx));
540 // First check If the MC Particle has been already cached
541 if(!fMCParticleMap->At(i)) {
542 // Get particle from the stack
543 particle = fStack->Particle(i);
544 // Get track references from Tree TR
546 fTreeTR->GetEntry(fStack->TreeKEntry(i));
548 ntref = trefs->GetEntriesFast();
549 rarray = new TObjArray(ntref);
550 Int_t nen = fTrackReferences->GetEntriesFast();
551 for (Int_t j = 0; j < ntref; j++) {
552 // Save the track references in a TClonesArray
553 AliTrackReference* ref = dynamic_cast<AliTrackReference*>((*fTRBuffer)[j]);
554 // Save the pointer in a TRefArray
556 new ((*fTrackReferences)[nen]) AliTrackReference(*ref);
557 rarray->AddAt((*fTrackReferences)[nen], j);
560 } // loop over track references for entry i
561 } // if TreeTR available
562 Int_t nentries = fMCParticles->GetEntriesFast();
563 mcParticle = new ((*fMCParticles)[nentries]) AliMCParticle(particle, rarray, i);
564 fMCParticleMap->AddAt(mcParticle, i);
566 TParticle* part = mcParticle->Particle();
567 Int_t imo = part->GetFirstMother();
568 Int_t id1 = part->GetFirstDaughter();
569 Int_t id2 = part->GetLastDaughter();
570 if (fPrimaryOffset > 0 || fSecondaryOffset > 0) {
571 // Remapping of the mother and daughter indices
572 if (imo < fNprimaries) {
573 mcParticle->SetMother(imo + fPrimaryOffset);
575 mcParticle->SetMother(imo + fSecondaryOffset - fNprimaries);
578 if (id1 < fNprimaries) {
579 mcParticle->SetFirstDaughter(id1 + fPrimaryOffset);
580 mcParticle->SetLastDaughter (id2 + fPrimaryOffset);
582 mcParticle->SetFirstDaughter(id1 + fSecondaryOffset - fNprimaries);
583 mcParticle->SetLastDaughter (id2 + fSecondaryOffset - fNprimaries);
587 if (i > fNprimaries) {
588 mcParticle->SetLabel(i + fPrimaryOffset);
590 mcParticle->SetLabel(i + fSecondaryOffset - fNprimaries);
593 mcParticle->SetFirstDaughter(id1);
594 mcParticle->SetLastDaughter (id2);
595 mcParticle->SetMother (imo);
599 mcParticle = dynamic_cast<AliMCParticle*>(fMCParticleMap->At(i));
602 //Printf("mcParticleGetMother %d",mcParticle->GetMother());
606 AliGenEventHeader* AliMCEvent::GenEventHeader() const
610 return (fHeader->GenEventHeader());
614 TList * lh = fAODMCHeader->GetCocktailHeaders();
615 if (lh) {return ((AliGenEventHeader*) lh->At(0));}
622 void AliMCEvent::AddSubsidiaryEvent(AliMCEvent* event)
624 // Add a subsidiary event to the list; for example merged background event.
625 if (!fSubsidiaryEvents) {
626 TList* events = new TList();
627 events->Add(new AliMCEvent(*this));
628 fSubsidiaryEvents = events;
631 fSubsidiaryEvents->Add(event);
634 AliGenEventHeader *AliMCEvent::FindHeader(Int_t ipart) {
636 // Get Header belonging to this track;
637 // only works for primaries (i.e. particles coming from the Generator)
638 // Also sorts out the case of Cocktail event (get header of subevent in cocktail generetor header)
641 AliMCEvent *event = this;
643 if (fSubsidiaryEvents) {
644 // Get pointer to subevent if needed
645 ipart = FindIndexAndEvent(ipart,event);
648 AliGenEventHeader* header = event->GenEventHeader();
649 if (ipart >= header->NProduced()) {
650 AliWarning(Form("Not a primary -- returning 0 (idx %d, nPrimary %d)",ipart,header->NProduced()));
653 AliGenCocktailEventHeader *coHeader = dynamic_cast<AliGenCocktailEventHeader*>(header);
654 if (coHeader) { // Cocktail event
655 TList* headerList = coHeader->GetHeaders();
656 TIter headIt(headerList);
658 do { // Go trhough all headers and look for the correct one
659 header = (AliGenEventHeader*) headIt();
660 if (header) nproduced += header->NProduced();
661 } while (header && ipart >= nproduced);
667 Int_t AliMCEvent::FindIndexAndEvent(Int_t oldidx, AliMCEvent*& event) const
669 // Find the index and event in case of composed events like signal + background
670 TIter next(fSubsidiaryEvents);
672 if (oldidx < fNprimaries) {
673 while((event = (AliMCEvent*)next())) {
674 if (oldidx < (event->GetPrimaryOffset() + event->GetNumberOfPrimaries())) break;
677 return (oldidx - event->GetPrimaryOffset());
682 while((event = (AliMCEvent*)next())) {
683 if (oldidx < (event->GetSecondaryOffset() + (event->GetNumberOfTracks() - event->GetNumberOfPrimaries()))) break;
686 return (oldidx - event->GetSecondaryOffset() + event->GetNumberOfPrimaries());
693 Int_t AliMCEvent::BgLabelToIndex(Int_t label)
695 // Convert a background label to an absolute index
696 if (fSubsidiaryEvents) {
697 AliMCEvent* bgEvent = (AliMCEvent*) (fSubsidiaryEvents->At(1));
698 label -= BgLabelOffset();
699 if (label < bgEvent->GetNumberOfPrimaries()) {
700 label += bgEvent->GetPrimaryOffset();
702 label += (bgEvent->GetSecondaryOffset() - fNprimaries);
709 Bool_t AliMCEvent::IsPhysicalPrimary(Int_t i) const
712 // Delegate to subevent if necesarry
715 if (!fSubsidiaryEvents) {
716 return fStack->IsPhysicalPrimary(i);
719 Int_t idx = FindIndexAndEvent(i, evt);
720 return (evt->IsPhysicalPrimary(idx));
724 Bool_t AliMCEvent::IsSecondaryFromWeakDecay(Int_t i)
727 // Delegate to subevent if necesarry
728 if (!fSubsidiaryEvents) {
729 return fStack->IsSecondaryFromWeakDecay(i);
732 Int_t idx = FindIndexAndEvent(i, evt);
733 return (evt->IsSecondaryFromWeakDecay(idx));
737 Bool_t AliMCEvent::IsSecondaryFromMaterial(Int_t i)
740 // Delegate to subevent if necesarry
741 if (!fSubsidiaryEvents) {
742 return fStack->IsSecondaryFromMaterial(i);
745 Int_t idx = FindIndexAndEvent(i, evt);
746 return (evt->IsSecondaryFromMaterial(idx));
751 void AliMCEvent::InitEvent()
754 // Initialize the subsidiary event structure
755 if (fSubsidiaryEvents) {
756 TIter next(fSubsidiaryEvents);
761 while((evt = (AliMCEvent*)next())) {
762 fNprimaries += evt->GetNumberOfPrimaries();
763 fNparticles += evt->GetNumberOfTracks();
767 Int_t ioffs = fNprimaries;
770 while((evt = (AliMCEvent*)next())) {
771 evt->SetPrimaryOffset(ioffp);
772 evt->SetSecondaryOffset(ioffs);
773 ioffp += evt->GetNumberOfPrimaries();
774 ioffs += (evt->GetNumberOfTracks() - evt->GetNumberOfPrimaries());
779 void AliMCEvent::PreReadAll()
781 // Preread the MC information
784 for (i = fStack->GetNprimary(); i < fStack->GetNtrack(); i++)
789 for (i = 0; i < fStack->GetNprimary(); i++)
793 AssignGeneratorIndex();
796 const AliVVertex * AliMCEvent::GetPrimaryVertex() const
798 // Create a MCVertex object from the MCHeader information
800 GenEventHeader()->PrimaryVertex(v) ;
802 fVertex = new AliMCVertex(v[0], v[1], v[2]);
804 ((AliMCVertex*) fVertex)->SetPosition(v[0], v[1], v[2]);
809 Bool_t AliMCEvent::IsFromBGEvent(Int_t index)
811 // Checks if a particle is from the background events
812 // Works for HIJING inside Cocktail
814 AliGenCocktailEventHeader* coHeader =
815 dynamic_cast<AliGenCocktailEventHeader*> (GenEventHeader());
816 if (!coHeader) return (0);
817 TList* list = coHeader->GetHeaders();
818 AliGenHijingEventHeader* hijingH = dynamic_cast<AliGenHijingEventHeader*>(list->FindObject("Hijing"));
819 if (!hijingH) return (0);
820 fNBG = hijingH->NProduced();
823 return (index < fNBG);
827 TList* AliMCEvent::GetCocktailList()
829 //gives the CocktailHeaders when reading ESDs/AODs (corresponding to fExteral=kFALSE/kTRUE)
830 //the AODMC header (and the aodmc array) is passed as an instance to MCEvent by the AliAODInputHandler
831 if(fExternal==kFALSE) {
832 AliGenCocktailEventHeader* coHeader =dynamic_cast<AliGenCocktailEventHeader*> (GenEventHeader());
836 return (coHeader->GetHeaders());
842 return (fAODMCHeader->GetCocktailHeaders());
848 TString AliMCEvent::GetGenerator(Int_t index)
850 Int_t nsumpart=fNprimaries;
851 TList* lh = GetCocktailList();
852 if(!lh){ TString noheader="nococktailheader";
854 Int_t nh=lh->GetEntries();
855 for (Int_t i = nh-1; i >= 0; i--){
856 AliGenEventHeader* gh=(AliGenEventHeader*)lh->At(i);
857 TString genname=gh->GetName();
858 Int_t npart=gh->NProduced();
859 if (i == 0) npart = nsumpart;
860 if(index < nsumpart && index >= (nsumpart-npart)) return genname;
867 void AliMCEvent::AssignGeneratorIndex() {
869 // Assign the generator index to each particle
871 TList* list = GetCocktailList();
872 if (fNprimaries <= 0) {
873 AliWarning(Form("AliMCEvent::AssignGeneratorIndex: no primaries %10d\n", fNprimaries));
879 Int_t nh = list->GetEntries();
880 Int_t nsumpart = fNprimaries;
881 for(Int_t i = nh-1; i >= 0; i--){
882 AliGenEventHeader* gh = (AliGenEventHeader*)list->At(i);
883 Int_t npart = gh->NProduced();
885 if (npart != nsumpart) {
886 // printf("Header inconsistent ! %5d %5d \n", npart, nsumpart);
891 // Loop over primary particles for generator i
892 for (Int_t j = nsumpart-1; j >= nsumpart-npart; j--) {
893 AliVParticle* part = GetTrack(j);
895 AliWarning(Form("AliMCEvent::AssignGeneratorIndex: 0-pointer to particle j %8d npart %8d nsumpart %8d Nprimaries %8d\n",
896 j, npart, nsumpart, fNprimaries));
899 part->SetGeneratorIndex(i);
900 Int_t dmin = part->GetFirstDaughter();
901 Int_t dmax = part->GetLastDaughter();
902 if (dmin == -1) continue;
903 AssignGeneratorIndex(i, dmin, dmax);
909 void AliMCEvent::AssignGeneratorIndex(Int_t index, Int_t dmin, Int_t dmax) {
910 for (Int_t k = dmin; k <= dmax; k++) {
911 AliVParticle* dpart = GetTrack(k);
912 dpart->SetGeneratorIndex(index);
913 Int_t d1 = dpart->GetFirstDaughter();
914 Int_t d2 = dpart->GetLastDaughter();
916 AssignGeneratorIndex(index, d1, d2);
921 Bool_t AliMCEvent::GetCocktailGenerator(Int_t index,TString &nameGen){
922 //method that gives the generator for a given particle with label index (or that of the corresponding primary)
923 AliVParticle* mcpart0 = (AliVParticle*) (GetTrack(index));
925 printf("AliMCEvent-BREAK: No valid AliMCParticle at label %i\n",index);
929 Int_t ig = mcpart0->GetGeneratorIndex();
931 nameGen = ((AliGenEventHeader*)GetCocktailList()->At(ig))->GetName();
935 nameGen=GetGenerator(index);
936 if(nameGen.Contains("nococktailheader") )return 0;
939 while(nameGen.IsWhitespace()){
942 AliVParticle* mcpart = (AliVParticle*) (GetTrack(lab));
945 printf("AliMCEvent-BREAK: No valid AliMCParticle at label %i\n",lab);
948 mother = mcpart->GetMother();
951 printf("AliMCEvent - BREAK: Reached primary particle without valid mother\n");
954 AliVParticle* mcmom = (AliVParticle*) (GetTrack(mother));
956 printf("AliMCEvent-BREAK: No valid AliMCParticle mother at label %i\n",mother);
961 nameGen=GetGenerator(mother);
967 void AliMCEvent::SetParticleArray(TClonesArray* mcParticles)
969 fMCParticles = mcParticles;
970 fNparticles = fMCParticles->GetEntries();
974 static Int_t binaryfirst(TClonesArray* a, Int_t low, Int_t high)
976 Int_t mid = low + (high - low)/2;
977 if (low > a->GetEntries()-1) return (a->GetEntries()-1);
978 if (!((AliVParticle*) a->At(mid))->IsPrimary()) {
979 if (mid > 1 && !((AliVParticle*) a->At(mid-1))->IsPrimary()) {
980 return binaryfirst(a, low, mid-1);
985 return binaryfirst(a, mid+1, high);
989 fNprimaries = Local::binaryfirst(mcParticles, 0, mcParticles->GetEntries()-1);
990 AssignGeneratorIndex();
993 AliVEvent::EDataLayoutType AliMCEvent::GetDataLayoutType() const
995 return AliVEvent::kMC;