Line data Source code
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 : //-------------------------------------------------------------------------
17 : // Class AliGenPileup
18 : // This is a generator of beam-beam pileup.
19 : // It generates interactions within 3 orbits (+-1) around
20 : // the trigger event. The trigger event itself is chosen
21 : // randomly among the bunch crossings within the central orbit.
22 : // The user can decide whenever to include in the simulation the
23 : // "trigger" interaction or not. This is handled by the
24 : // GenerateTrigInteraction(Bool_t flag) method.
25 : // In the case the trigger interaction is included, it is
26 : // generated using the same settings (vertex smear for example) as
27 : // the pileup events.
28 : // In case the trigger simulation is not included, the user can make
29 : // a cocktail of generator used to produce the trigger interaction and
30 : // AliGenPileup. In this case in order to avoid a fake increase of the rate around the
31 : // trigger, the number of background events within the bunch
32 : // crossing of the trigger is readuced by one.
33 : // The beam profile (the list of the active bunch crossings) can be
34 : // controlled via the SetBCMask(const char *mask) method. The syntax
35 : // follows the one in AliTriggerBCMask class. For example:
36 : // "3564H" would mean that all the bunch corssings within the orbit
37 : // are aloowed (which is of course unphysical). In case one wants to simulate
38 : // one-bunch-crossing-per-orbit scenario, the way to do it is to put something like:
39 : // "1H3563L" or similar.
40 : // The SetGenerator(AliGenerator *generator, Float_t rate) method is
41 : // used in order to define the generator to be used. The second argument is the pileup
42 : // rate in terms of #_of_interactions/bunch-crossing = sigma_tot * luminosity.
43 : // The pileup generation time window can be set via
44 : // AliGenerator::SetPileUpTimeWindow(Float_t pileUpTimeW) method. By the default the
45 : // window is set to 88micros (= TPC readout window).
46 : //
47 : // cvetan.cheshkov@cern.ch 9/12/2008
48 : //-------------------------------------------------------------------------
49 :
50 : #include <TParticle.h>
51 : #include <TFormula.h>
52 :
53 : #include "AliGenPileup.h"
54 : #include "AliLog.h"
55 : #include "AliGenCocktailEventHeader.h"
56 : #include "AliGenCocktailEntry.h"
57 : #include "AliRun.h"
58 : #include "AliStack.h"
59 :
60 6 : ClassImp(AliGenPileup)
61 :
62 : AliGenPileup::AliGenPileup():
63 0 : AliGenCocktail(),
64 0 : fBCMask("bcm","3564H"),
65 0 : fGenTrig(kFALSE),
66 0 : fFlag(kFALSE)
67 0 : {
68 : // Constructor
69 : // The pileup time window is by default
70 : // set to the TPC readout one
71 0 : fName = "Pileup";
72 0 : fTitle= "Beam-beam pileup";
73 :
74 0 : fPileUpTimeWindow = 88e-6;
75 0 : }
76 :
77 0 : AliGenPileup::~AliGenPileup()
78 0 : {
79 : // Destructor
80 0 : }
81 :
82 : void AliGenPileup::SetGenerator(AliGenerator *generator, Float_t rate, Bool_t flag)
83 : {
84 : // The method sets the geenrator to be used
85 : // for pileup simulation.
86 : // The second argument is the pileup rate in terms of
87 : // #_of_interactions/bunch-crossing = sigma_tot * luminosity.
88 : // There is a protection in case the generator was already set.
89 0 : if (fEntries) {
90 0 : if (FirstGenerator()) {
91 0 : AliError("Pileup generator has been already set! Nothing done");
92 0 : return;
93 : }
94 : }
95 0 : AddGenerator(generator,"pileup generator",rate);
96 0 : fFlag = flag;
97 0 : }
98 :
99 : void AliGenPileup::AddGenerator(AliGenerator *Generator,
100 : const char* Name,
101 : Float_t RateExp , TFormula* /*form*/, Int_t /*ntimes*/)
102 : {
103 : // The method used to add the pileup generator
104 : // in the cocktail list.
105 : // The method is protected in order to avoid
106 : // its misusage
107 0 : AliGenCocktail::AddGenerator(Generator,Name,RateExp);
108 0 : }
109 :
110 : Bool_t AliGenPileup::SetBCMask(const char *mask)
111 : {
112 : // Set the active bunch-crossings that
113 : // will be included in the pileup
114 : // simulation. For more details on the
115 : // syntax of the mask - see
116 : // STEER/AliTriggerBCMask.* and the comments
117 : // in the header of this file
118 0 : return fBCMask.SetMask(mask);
119 : }
120 :
121 : void AliGenPileup::Generate()
122 : {
123 : //
124 : // Generate pileup event
125 : // For details see the coments inline
126 :
127 : // Check that the pileup generator is correctly set
128 0 : AliGenCocktailEntry *entry = FirstGenerator();
129 0 : if (!entry) {
130 0 : AliFatal("No pileup generator entry is found!");
131 0 : }
132 :
133 0 : AliGenerator *gen = entry->Generator();
134 0 : if (!gen) {
135 0 : AliFatal("No pileup generator specified!");
136 0 : }
137 0 : else if (gen->NeedsCollisionGeometry()) {
138 0 : AliFatal("No Collision Geometry Provided");
139 0 : }
140 :
141 : // Check that the pileup rate is correctly set
142 0 : Float_t rate = entry->Rate();
143 0 : if (rate <= 0) {
144 0 : AliFatal(Form("Invalid rate value: %f",rate));
145 0 : }
146 :
147 : // Create cocktail header
148 0 : if (fHeader) delete fHeader;
149 0 : fHeader = new AliGenCocktailEventHeader("Pileup Cocktail Header");
150 :
151 : // Generate time of all
152 : // the collisions within one orbit
153 0 : Int_t *nIntBC = new Int_t[3*AliTriggerBCMask::kNBits];
154 0 : Int_t *indexBC = new Int_t[3*AliTriggerBCMask::kNBits];
155 : Int_t nTotBC = 0;
156 0 : while (nTotBC == 0) {
157 0 : for(Int_t iBC = 0; iBC < AliTriggerBCMask::kNBits; iBC++) {
158 :
159 0 : if (!fBCMask.GetMask(iBC)) continue;
160 :
161 : // Int_t nInteractions = gRandom->Poisson(rate);
162 : Int_t nInteractions;
163 0 : if (!fFlag)
164 0 : nInteractions = gRandom->Poisson(rate);
165 : else
166 0 : nInteractions = TMath::Nint(rate) + 1;
167 :
168 0 : if (nInteractions == 0) continue;
169 :
170 0 : nIntBC[nTotBC] = nInteractions;
171 0 : indexBC[nTotBC] = iBC;
172 0 : nTotBC++;
173 0 : }
174 : }
175 :
176 : // Select the bunch crossing for triggered event
177 0 : Int_t iTrgBC = gRandom->Integer(nTotBC);
178 : // Subtract one from the number of events
179 : // generated within this bc (only in case
180 : // the user disabled the generation of the trigger
181 : // interaction)
182 0 : if (!fGenTrig) nIntBC[iTrgBC]--;
183 :
184 : // Remove bunch crossings outside pileup
185 : // time window
186 0 : for(Int_t iBC = 0; iBC < nTotBC; iBC++) {
187 0 : if (TMath::Abs(25e-9*(indexBC[iBC]-indexBC[iTrgBC])) > fPileUpTimeWindow)
188 0 : nIntBC[iBC] = 0;
189 : }
190 :
191 : // Generate the two orbits around the central one
192 : // taking into account the pileup time window
193 0 : for(Int_t iBC = 0; iBC < AliTriggerBCMask::kNBits; iBC++) {
194 :
195 0 : if (!fBCMask.GetMask(iBC)) continue;
196 :
197 0 : if (TMath::Abs(25e-9*(iBC-AliTriggerBCMask::kNBits-indexBC[iTrgBC])) > fPileUpTimeWindow) continue;
198 :
199 0 : Int_t nInteractions = gRandom->Poisson(rate);
200 0 : if (nInteractions == 0) continue;
201 :
202 0 : nIntBC[nTotBC] = nInteractions;
203 0 : indexBC[nTotBC] = iBC-AliTriggerBCMask::kNBits;
204 0 : nTotBC++;
205 0 : }
206 0 : for(Int_t iBC = 0; iBC < AliTriggerBCMask::kNBits; iBC++) {
207 :
208 0 : if (!fBCMask.GetMask(iBC)) continue;
209 :
210 0 : if (TMath::Abs(25e-9*(iBC+AliTriggerBCMask::kNBits-indexBC[iTrgBC])) > fPileUpTimeWindow) continue;
211 :
212 0 : Int_t nInteractions = gRandom->Poisson(rate);
213 0 : if (nInteractions == 0) continue;
214 :
215 0 : nIntBC[nTotBC] = nInteractions;
216 0 : indexBC[nTotBC] = iBC+AliTriggerBCMask::kNBits;
217 0 : nTotBC++;
218 0 : }
219 :
220 : // Loop over the generated collision times, call the generator
221 : // and correct the partcile times in the stack
222 0 : AliStack *stack = AliRunLoader::Instance()->Stack();
223 : Int_t lastpart=0;
224 0 : entry->SetFirst(lastpart);
225 :
226 0 : for(Int_t iBC = 0; iBC < nTotBC; iBC++) {
227 0 : Float_t deltat = 25e-9*(indexBC[iBC] - indexBC[iTrgBC]);
228 0 : for (Int_t i = 0; i < nIntBC[iBC]; i++) {
229 : // Generate the vertex position and time
230 0 : Vertex();
231 0 : TArrayF eventVertex(3);
232 0 : for (Int_t j=0; j < 3; j++) eventVertex[j] = fVertex[j];
233 0 : Double_t vTime = deltat + gRandom->Gaus(0,fOsigma[2]/TMath::Ccgs());
234 :
235 0 : gen->SetVertex(fVertex.At(0), fVertex.At(1), fVertex.At(2));
236 0 : gen->Generate();
237 :
238 0 : for (Int_t k = lastpart; k < stack->GetNprimary(); k++) {
239 0 : TLorentzVector v;
240 0 : stack->Particle(k)->ProductionVertex(v);
241 0 : v[3] = vTime;
242 0 : stack->Particle(k)->SetProductionVertex(v);
243 0 : }
244 0 : lastpart = stack->GetNprimary();
245 :
246 : // Store the interaction header in the container of the headers
247 0 : ((AliGenEventHeader*) fHeader->GetHeaders()->Last())->SetPrimaryVertex(eventVertex);
248 0 : ((AliGenEventHeader*) fHeader->GetHeaders()->Last())->SetInteractionTime(vTime);
249 0 : }
250 : }
251 0 : delete [] nIntBC;
252 0 : delete [] indexBC;
253 :
254 0 : entry->SetLast(stack->GetNprimary());
255 :
256 0 : fHeader->CalcNProduced();
257 :
258 0 : if (fContainer) {
259 0 : fHeader->SetName(fName);
260 0 : fContainer->AddHeader(fHeader);
261 0 : } else {
262 0 : gAlice->SetGenEventHeader(fHeader);
263 : }
264 :
265 0 : }
266 :
267 : void AliGenPileup::SetRandomise(Bool_t /*flag*/)
268 : {
269 : // This setting is not implemented in
270 : // case of pileup generation
271 : // So the method gives an warning and exits
272 0 : AliWarning("This setting has no effect on the generator!");
273 0 : }
274 :
275 : void AliGenPileup::UsePerEventRates()
276 : {
277 : // This setting is not implemented in
278 : // case of pileup generation
279 : // So the method gives an warning and exits
280 0 : AliWarning("This setting has no effect on the generator!");
281 0 : }
|