8ede90788fec6495f130c575174a63fd11caee33
[u/mrichter/AliRoot.git] / EVGEN / AliGenCocktail.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, 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 // Container class for AliGenerator through recursion.
19 // Container is itself an AliGenerator.
20 // What is stored are not the pointers to the generators directly but to objects of type
21 // AliGenCocktail entry.   
22 // The class provides also iterator functionality.  
23 // Author: andreas.morsch@cern.ch 
24 //
25
26 #include <TList.h>
27 #include <TObjArray.h>
28
29 #include "AliGenCocktail.h"
30 #include "AliGenCocktailEntry.h"
31 #include "AliCollisionGeometry.h"
32 #include "AliRun.h"
33 #include "AliMC.h"
34 #include "AliGenCocktailEventHeader.h"
35
36 ClassImp(AliGenCocktail)
37
38 AliGenCocktail::AliGenCocktail()
39                  :AliGenerator()
40 {
41 // Constructor
42     fName = "Cocktail";
43     fTitle= "Particle Generator using cocktail of generators";
44     flnk1 = 0;
45     flnk2 = 0;
46     fNGenerators=0;
47     fEntries = 0;
48     fRandom  = kFALSE;
49     fHeader  = 0;
50 }
51
52 AliGenCocktail::AliGenCocktail(const AliGenCocktail & cocktail):
53     AliGenerator(cocktail)
54 {
55 // Copy constructor
56     cocktail.Copy(*this);
57 }
58
59 AliGenCocktail::~AliGenCocktail()
60 {
61 // Destructor
62     delete fEntries;
63     delete fHeader;
64 }
65
66 void AliGenCocktail::
67 AddGenerator(AliGenerator *Generator, const char* Name, Float_t RateExp)
68 {
69 //
70 // Add a generator to the list 
71 // First check that list exists
72     if (!fEntries) fEntries = new TList();
73
74 //
75 //  Forward parameters to the new generator
76     if(TestBit(kPtRange) && !(Generator->TestBit(kPtRange)) && !(Generator->TestBit(kMomentumRange))) 
77         Generator->SetPtRange(fPtMin,fPtMax);
78     if(TestBit(kMomentumRange) && !(Generator->TestBit(kPtRange)) && !(Generator->TestBit(kMomentumRange)))
79         Generator->SetMomentumRange(fPMin,fPMax);
80     
81     if (!(Generator->TestBit(kYRange)))    
82         Generator->SetYRange(fYMin,fYMax);
83     if (!(Generator->TestBit(kPhiRange)))   
84         Generator->SetPhiRange(fPhiMin*180/TMath::Pi(),fPhiMax*180/TMath::Pi());
85     if (!(Generator->TestBit(kThetaRange))) 
86         Generator->SetThetaRange(fThetaMin*180/TMath::Pi(),fThetaMax*180/TMath::Pi());
87     if (!(Generator->TestBit(kVertexRange))) 
88         Generator->SetOrigin(fOrigin[0], fOrigin[1], fOrigin[2]);
89
90     Generator->SetSigma(fOsigma[0], fOsigma[1], fOsigma[2]);
91     Generator->SetVertexSmear(fVertexSmear);
92     Generator->SetVertexSource(kContainer);
93     Generator->SetTrackingFlag(fTrackIt);
94     Generator->SetContainer(this);
95     
96         
97 //
98 //  Add generator to list   
99     char theName[256];
100     sprintf(theName, "%s_%d",Name, fNGenerators);
101     Generator->SetName(theName);
102
103     AliGenCocktailEntry *entry = 
104         new AliGenCocktailEntry(Generator, Name, RateExp);
105     
106      fEntries->Add(entry);
107      fNGenerators++;
108  }
109
110   void AliGenCocktail::Init()
111 {
112 // Initialisation
113     TIter next(fEntries);
114     AliGenCocktailEntry *entry;
115     //
116     // Loop over generators and initialize
117     while((entry = (AliGenCocktailEntry*)next())) {
118         if (fStack)  entry->Generator()->SetStack(fStack);
119         entry->Generator()->Init();
120     }  
121
122     next.Reset();
123
124     if (fRandom) {
125         fProb.Set(fNGenerators);
126         next.Reset();
127         Float_t sum = 0.;
128         while((entry = (AliGenCocktailEntry*)next())) {
129             sum += entry->Rate();
130         } 
131
132         next.Reset();
133         Int_t i = 0;
134         Float_t psum = 0.;
135         while((entry = (AliGenCocktailEntry*)next())) {
136             psum +=  entry->Rate() / sum;
137             fProb[i++] = psum;
138         }
139     }
140         next.Reset();
141 }
142
143   void AliGenCocktail::FinishRun()
144 {
145 // Initialisation
146     TIter next(fEntries);
147     AliGenCocktailEntry *entry;
148     //
149     // Loop over generators and initialize
150     while((entry = (AliGenCocktailEntry*)next())) {
151         entry->Generator()->FinishRun();
152     }  
153 }
154
155  void AliGenCocktail::Generate()
156 {
157 //
158 // Generate event 
159     TIter next(fEntries);
160     AliGenCocktailEntry *entry = 0;
161     AliGenCocktailEntry *preventry = 0;
162     AliGenerator* gen = 0;
163     if (fHeader) delete fHeader;
164     fHeader = new AliGenCocktailEventHeader("Cocktail Header");
165
166     TObjArray *partArray = gAlice->GetMCApp()->Particles();
167
168 //
169 //  Generate the vertex position used by all generators
170 //    
171     if(fVertexSmear == kPerEvent) Vertex();
172
173     TArrayF eventVertex;
174     eventVertex.Set(3);
175     for (Int_t j=0; j < 3; j++) eventVertex[j] = fVertex[j];
176
177     if (!fRandom) {
178         //
179         // Loop over generators and generate events
180         Int_t igen=0;
181         
182         while((entry = (AliGenCocktailEntry*)next())) {
183             igen++;
184             if (igen ==1) {
185                 entry->SetFirst(0);
186             } else {
187                 entry->SetFirst((partArray->GetEntriesFast())+1);
188             }
189 //
190 //      Handle case in which current generator needs collision geometry from previous generator
191 //
192             gen = entry->Generator();
193             if (gen->NeedsCollisionGeometry())
194             {
195                 if (preventry && preventry->Generator()->ProvidesCollisionGeometry())
196                 {
197                     gen->SetCollisionGeometry(preventry->Generator()->CollisionGeometry());
198                 } else {
199                     Fatal("Generate()", "No Collision Geometry Provided");
200                 }
201             }
202             entry->Generator()->SetVertex(fVertex.At(0), fVertex.At(1), fVertex.At(2));
203             entry->Generator()->Generate();
204             entry->SetLast(partArray->GetEntriesFast());
205             preventry = entry;
206         }  
207     } else {
208         //
209         // Select a generator randomly
210         //
211         Int_t i;
212         Float_t p0 =  gRandom->Rndm();
213
214         for (i = 0; i < fNGenerators; i++) {
215             if (p0 < fProb[i]) break;
216         }
217
218         entry = (AliGenCocktailEntry*) fEntries->At(i);
219         entry->SetFirst(0);
220         gen = entry->Generator();
221         entry->Generator()->SetVertex(fVertex.At(0), fVertex.At(1), fVertex.At(2));
222         entry->Generator()->Generate();
223         entry->SetLast(partArray->GetEntriesFast());
224     }
225     
226     
227     next.Reset();
228
229 // Event Vertex
230     fHeader->SetPrimaryVertex(eventVertex);
231     gAlice->SetGenEventHeader(fHeader); 
232 }
233
234 void AliGenCocktail::SetVertexSmear(VertexSmear_t smear)
235 {
236 // Set vertex smearing and propagate it to the generators
237
238   AliGenerator::SetVertexSmear(smear);
239   TIter next(fEntries);
240   while (AliGenCocktailEntry* entry = (AliGenCocktailEntry*)next()) {
241     entry->Generator()->SetVertexSmear(smear);
242   }
243 }
244
245 AliGenCocktailEntry *  AliGenCocktail::FirstGenerator()
246 {
247 // Iterator over generators: Initialisation
248     flnk1 = fEntries->FirstLink();
249     if (flnk1) {
250         return (AliGenCocktailEntry*) (flnk1->GetObject());
251     } else {
252         return 0;
253     }
254 }
255
256 AliGenCocktailEntry*  AliGenCocktail::NextGenerator()
257 {
258 // Iterator over generators: Increment
259     flnk1 = flnk1->Next();
260     if (flnk1) {
261         return (AliGenCocktailEntry*) (flnk1->GetObject());
262     } else {
263         return 0;
264     }
265 }
266
267 void AliGenCocktail::
268 FirstGeneratorPair(AliGenCocktailEntry*& e1, AliGenCocktailEntry*& e2)
269 {
270 // Iterator over generator pairs: Initialisation
271     flnk2 = flnk1 = fEntries->FirstLink();
272     if (flnk1) {
273         e2 = e1 = (AliGenCocktailEntry*) (flnk1->GetObject());
274     } else {
275         e2= e1 = 0;
276     }
277 }
278
279 void AliGenCocktail::
280 NextGeneratorPair(AliGenCocktailEntry*& e1, AliGenCocktailEntry*& e2)
281 {
282 // Iterator over generators: Increment
283     flnk2 = flnk2->Next();
284     if (flnk2) {
285         e1 = (AliGenCocktailEntry*) (flnk1->GetObject());
286         e2 = (AliGenCocktailEntry*) (flnk2->GetObject());       
287     } else {
288         flnk2 = flnk1 = flnk1->Next();
289         if (flnk1) {
290             e1 = (AliGenCocktailEntry*) (flnk1->GetObject());
291             e2 = (AliGenCocktailEntry*) (flnk2->GetObject());
292         } else {
293             e1=0;
294             e2=0;
295         }
296     }
297 }
298
299 void AliGenCocktail::AddHeader(AliGenEventHeader* header)
300 {
301 // Add a header to the list 
302     if (fHeader) fHeader->AddHeader(header);
303 }
304                               
305 AliGenCocktail& AliGenCocktail::operator=(const  AliGenCocktail& rhs)
306 {
307 // Assignment operator
308     rhs.Copy(*this); 
309     return (*this);
310 }
311
312 void AliGenCocktail::Copy(TObject &) const
313 {
314     Fatal("Copy","Not implemented!\n");
315 }
316
317
318