]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliCollider.cxx
30-nov-2002 NvE Vertex position errors based on fResolution introduced in AliCollider...
[u/mrichter/AliRoot.git] / RALICE / AliCollider.cxx
1 // $Id: AliCollider.cxx,v 1.2 2002/11/29 13:54:52 nick Exp $
2
3 ///////////////////////////////////////////////////////////////////////////
4 // Class AliCollider
5 // Pythia based universal physics event generator.
6 // This class is derived from TPythia6 and has some extensions to
7 // support also generation of nucleus-nucleus interactions and to allow
8 // investigation of the effect of detector resolving power.
9 // Furthermore, the produced event information is provided in a format
10 // using the AliEvent structure.
11 // For the produced AliTrack objects, the particle ID code is set to the
12 // Pythia KF value, which is compatible with the PDG identifier.
13 // This will allow a direct analysis of the produced data using the
14 // Ralice physics analysis tools.
15 //
16 // For further details concerning the produced output structure,
17 // see the docs of the memberfunctions SetVertexMode and SetResolution.
18 //
19 // Example job of minimum biased Pb+Pb interactions :
20 // --------------------------------------------------
21 // {
22 //  gSystem->Load("libEG");
23 //  gSystem->Load("libEGPythia6");
24 //  gSystem->Load("ralice");
25 //
26 //  AliCollider* gen=new AliCollider();
27 //
28 //  gen->SetOutputFile("test.root");
29 //  gen->SetVertexMode(3);    
30 //  gen->SetResolution(1e-4); // 1 micron vertex resolution
31 //
32 //  gen->SetRunNumber(1);
33 //
34 //  Int_t zp=82;
35 //  Int_t ap=208;
36 //  Int_t zt=82;
37 //  Int_t at=208;
38 //
39 //  gen->Init("fixt",zp,ap,zt,at,158);
40 //
41 //  Int_t nevents=5;
42 //
43 //  AliRandom rndm;
44 //  Float_t* rans=new Float_t[nevents];
45 //  rndm.Uniform(rans,nevents,2,ap+at);
46 //  Int_t npart;
47 //  for (Int_t i=0; i<nevents; i++)
48 //  {
49 //   npart=rans[i];
50 //   gen->MakeEvent(npart);
51 //
52 //   AliEvent* evt=gen->GetEvent();
53 //  
54 //   evt->List();
55 //  }
56 //
57 //  gen->EndRun();
58 // }
59 //
60 //
61 // Example job of a cosmic nu+p atmospheric interaction.
62 // -----------------------------------------------------
63 // {
64 //  gSystem->Load("libEG");
65 //  gSystem->Load("libEGPythia6");
66 //  gSystem->Load("ralice");
67 //
68 //  AliCollider* gen=new AliCollider();
69 //
70 //  gen->SetOutputFile("test.root");
71 //
72 //  gen->SetRunNumber(1);
73 //
74 //  gen->Init("fixt","nu_mu","p",1e11);
75 //
76 //  Int_t nevents=10;
77 //
78 //  for (Int_t i=0; i<nevents; i++)
79 //  {
80 //   gen->MakeEvent(0,1);
81 //
82 //   AliEvent* evt=gen->GetEvent();
83 //  
84 //   evt->Info();
85 //  }
86 //
87 //  gen->EndRun();
88 // }
89 //
90 //
91 //--- Author: Nick van Eijndhoven 22-nov-2002 Utrecht University
92 //- Modified: NvE $Date: 2002/11/29 13:54:52 $ Utrecht University
93 ///////////////////////////////////////////////////////////////////////////
94
95 #include "AliCollider.h"
96  
97 ClassImp(AliCollider) // Class implementation to enable ROOT I/O
98  
99 AliCollider::AliCollider()
100 {
101 // Default constructor.
102 // All variables initialised to default values.
103  fVertexmode=0;    // No vertex structure creation
104  fResolution=1e-5; // Standard resolution is 0.1 micron
105  fRunnum=0;
106  fEventnum=0;
107  fPrintfreq=1;
108
109  fEvent=0;
110
111  fFrame="none";
112  fWin=0;
113
114  fNucl=0;
115  fZproj=0;
116  fAproj=0;
117  fZtarg=0;
118  fAtarg=0;
119  fFracpp=0;
120  fFracnp=0;
121  fFracpn=0;
122  fFracnn=0;
123
124  fOutFile=0;
125  fOutTree=0;
126 }
127 ///////////////////////////////////////////////////////////////////////////
128 AliCollider::~AliCollider()
129 {
130 // Default destructor
131  if (fEvent)
132  {
133   delete fEvent;
134   fEvent=0;
135  }
136  if (fOutFile)
137  {
138   delete fOutFile;
139   fOutFile=0;
140  }
141  if (fOutTree)
142  {
143   delete fOutTree;
144   fOutTree=0;
145  }
146 }
147 ///////////////////////////////////////////////////////////////////////////
148 void AliCollider::SetOutputFile(TString s)
149 {
150 // Create the output file containing all the data in ROOT output format.
151  if (fOutFile)
152  {
153   delete fOutFile;
154   fOutFile=0;
155  }
156  fOutFile=new TFile(s.Data(),"RECREATE","AliCollider data");
157
158  if (fOutTree)
159  {
160   delete fOutTree;
161   fOutTree=0;
162  }
163  fOutTree=new TTree("T","AliCollider event data");
164
165  Int_t bsize=32000;
166  Int_t split=0;
167  fOutTree->Branch("Events","AliEvent",&fEvent,bsize,split);
168 }
169 ///////////////////////////////////////////////////////////////////////////
170 void AliCollider::SetVertexMode(Int_t mode)
171 {
172 // Set the mode of the vertex structure creation.
173 //
174 // By default all generated tracks will only appear in the AliEvent
175 // structure without any primary (and secondary) vertex structure.
176 // The user can build the vertex structure if he/she wants by means
177 // of the beginpoint location of each AliTrack.
178 //
179 // However, one can also let AliCollider automatically create
180 // the primary (and secondary) vertex structure(s).
181 // In this case the primary vertex is given Id=1 and all sec. vertices
182 // are given Id's 2,3,4,....
183 // All vertices are created as standalone entities in the AliEvent structure
184 // without any linking between the various vertices.
185 // For this automated process, the user-selected resolution
186 // (see SetResolution) is used to decide whether or not certain vertex
187 // locations can be resolved.
188 // In case no vertex creation is selected (i.e. the default mode=0),
189 // the value of the resolution is totally irrelevant.
190 //
191 // The user can also let AliCollider automatically connect the sec. vertices
192 // to the primary vertex (i.e. mode=3). This process will also automatically
193 // generate the tracks connecting the vertices.
194 // Note that the result of the mode=3 operation may be very sensitive to
195 // the resolution parameter. Therefore, no attempt is made to distinguish
196 // between secondary, tertiary etc... vertices. All sec. vertices are
197 // linked to the primary one.
198 //  
199 // Irrespective of the selected mode, all generated tracks can be obtained
200 // directly from the AliEvent structure.
201 // In case (sec.) vertex creation is selected, all generated vertices can
202 // also be obtained directly from the AliEvent structure. 
203 // These (sec.) vertices contain only the corresponding pointers to the various
204 // tracks which are stored in the AliEvent structure.
205 //
206 // Overview of vertex creation modes :
207 // -----------------------------------
208 // mode = 0 ==> No vertex structure will be created
209 //        1 ==> Only primary vertex structure will be created
210 //        2 ==> Unconnected primary and secondary vertices will be created
211 //        3 ==> Primary and secondary vertices will be created where all the
212 //              sec. vertices will be connected to the primary vertex.
213 //              Also the vertex connecting tracks will be automatically
214 //              generated. 
215 //
216  if (mode<0 || mode >3)
217  {
218   cout << " *AliCollider::SetVertexMode* Invalid argument mode : " << mode << endl;
219   fVertexmode=0;
220  }
221  else
222  {
223   fVertexmode=mode;
224  }
225 }
226 ///////////////////////////////////////////////////////////////////////////
227 Int_t AliCollider::GetVertexMode()
228 {
229 // Provide the current mode for vertex structure creation.
230  return fVertexmode;
231 }
232 ///////////////////////////////////////////////////////////////////////////
233 void AliCollider::SetResolution(Double_t res)
234 {
235 // Set the resolution (in cm) for resolving (sec.) vertices.
236 // By default this resolution is set to 0.1 micron.
237 // Note : In case no vertex creation has been selected, the value of
238 //        the resolution is totally irrelevant.
239  fResolution=fabs(res);
240 }
241 ///////////////////////////////////////////////////////////////////////////
242 Double_t AliCollider::GetResolution()
243 {
244 // Provide the current resolution (in cm) for resolving (sec.) vertices.
245  return fResolution;
246 }
247 ///////////////////////////////////////////////////////////////////////////
248 void AliCollider::SetRunNumber(Int_t run)
249 {
250 // Set the user defined run number.
251 // By default the run number is set to 0.
252  fRunnum=run;
253 }
254 ///////////////////////////////////////////////////////////////////////////
255 Int_t AliCollider::GetRunNumber()
256 {
257 // Provide the user defined run number.
258  return fRunnum;
259 }
260 ///////////////////////////////////////////////////////////////////////////
261 void AliCollider::SetPrintFreq(Int_t n)
262 {
263 // Set the print frequency for every 'n' events.
264 // By default the printfrequency is set to 1 (i.e. every event).
265  fPrintfreq=n;
266 }
267 ///////////////////////////////////////////////////////////////////////////
268 Int_t AliCollider::GetPrintFreq()
269 {
270 // Provide the user selected print frequency.
271  return fPrintfreq;
272 }
273 ///////////////////////////////////////////////////////////////////////////
274 void AliCollider::Init(char* frame,char* beam,char* target,Float_t win)
275 {
276 // Initialisation of the underlying Pythia generator package.
277 // This routine just invokes TPythia6::Initialize(...) and the arguments
278 // have the corresponding meaning.
279 // The event number is reset to 0.
280  fEventnum=0;
281  fNucl=0;
282  fFrame=frame;
283  fWin=win;
284  Initialize(frame,beam,target,win);
285 }
286 ///////////////////////////////////////////////////////////////////////////
287 void AliCollider::Init(char* frame,Int_t zp,Int_t ap,Int_t zt,Int_t at,Float_t win)
288 {
289 // Initialisation of the underlying Pythia generator package for the generation
290 // of nucleus-nucleus interactions.
291 // In addition to the Pythia standard arguments 'frame' and 'win', the user
292 // can specify here (Z,A) values of the projectile and target nuclei.
293 //
294 // Note : The 'win' value denotes either the cms energy per nucleon-nucleon collision
295 //        (i.e. frame="cms") or the momentum per nucleon in all other cases.
296 //
297 // The event number is reset to 0.
298  fEventnum=0;
299  fNucl=1;
300  fFrame=frame;
301  fWin=win;
302  fZproj=0;
303  fAproj=0;
304  fZtarg=0;
305  fAtarg=0;
306  fFracpp=0;
307  fFracnp=0;
308  fFracpn=0;
309  fFracnn=0;
310
311  if (ap<1 || at<1 || zp>ap || zt>at)
312  {
313   cout << " *AliCollider::Init* Invalid input value(s). Zproj = " << zp
314        << " Aproj = " << ap << " Ztarg = " << zt << " Atarg = " << at << endl;
315   return;
316  }
317
318  fZproj=zp;
319  fAproj=ap;
320  fZtarg=zt;
321  fAtarg=at;
322
323  cout << " *AliCollider::Init* Nucleus-Nucleus generator initialisation." << endl;
324  cout << " Zproj = " << zp << " Aproj = " << ap << " Ztarg = " << zt << " Atarg = " << at
325       << " Frame = " << frame << " Energy = " << win
326       << endl;
327 }
328 ///////////////////////////////////////////////////////////////////////////
329 void AliCollider::GetFractions(Float_t zp,Float_t ap,Float_t zt,Float_t at)
330 {
331 // Determine the fractions for the various N-N collision processes.
332 // The various processes are : p+p, n+p, p+n and n+n.
333  if (zp<0) zp=0;
334  if (zt<0) zt=0;
335
336  fFracpp=0;
337  fFracnp=0;
338  fFracpn=0;
339  fFracnn=0;
340
341  if (ap>0 && at>0)
342  {
343   fFracpp=(zp/ap)*(zt/at);
344   fFracnp=(1.-zp/ap)*(zt/at);
345   fFracpn=(zp/ap)*(1.-zt/at);
346   fFracnn=(1.-zp/ap)*(1.-zt/at);
347  }
348 }
349 ///////////////////////////////////////////////////////////////////////////
350 void AliCollider::MakeEvent(Int_t npt,Int_t mlist,Int_t medit)
351 {
352 // Generate one event.
353 // In case of a nucleus-nucleus interaction, the argument 'npt' denotes
354 // the number of participant nucleons.
355 // In case of a standard Pythia run for 'elementary' particle interactions,
356 // the value of npt is totally irrelevant.
357 //
358 // The argument 'medit' denotes the edit mode used for Pyedit().
359 // Note : medit<0 suppresses the invokation of Pyedit().
360 // By default, only 'stable' final particles are kept (i.e. medit=1). 
361 //
362 // The argument 'mlist' denotes the list mode used for Pylist().
363 // Note : mlist<0 suppresses the invokation of Pylist().
364 // By default, no listing is produced (i.e. mlist=-1).
365 //
366 // In the case of a standard Pythia run concerning 'elementary' particle
367 // interactions, the projectile and target particle ID's for the created
368 // event structure are set to the corresponding Pythia KF codes.
369 // All the A and Z values are in that case set to zero.
370 // In case of a nucleus-nucleus interaction, the proper A and Z values for 
371 // the projectile and target particles are set in the event structure.
372 // However, in this case both particle ID's are set to zero.
373
374  fEventnum++; 
375
376  // Counters for the various (proj,targ) combinations : p+p, n+p, p+n and n+n
377  Int_t ncols[4]={0,0,0,0};
378
379  if (fNucl)
380  {
381   if (npt<1 || npt>(fAproj+fAtarg))
382   {
383    cout << " *AliCollider::MakeEvent* Invalid input value. npt = " << npt
384         << " Aproj = " << fAproj << " Atarg = " << fAtarg << endl;
385    return;
386   }
387
388   // Determine the number of nucleon-nucleon collisions
389   Int_t ncol=npt/2.;
390   if (npt%2 && fRan.Uniform()>0.5) ncol+=1;
391
392   // Determine the number of the various types of N+N interactions
393   Int_t zp=fZproj;
394   Int_t ap=fAproj;
395   Int_t zt=fZtarg;
396   Int_t at=fAtarg;
397   Int_t maxa=2; // Indicator whether proj (1) or target (2) has maximal A left
398   if (ap>at) maxa=1;
399   Float_t* rans=new Float_t[ncol];
400   fRan.Uniform(rans,ncol);
401   Float_t rndm=0;
402   for (Int_t i=0; i<ncol; i++)
403   {
404    GetFractions(zp,ap,zt,at);
405    rndm=rans[i];
406    if (rndm<=fFracpp) // p+p interaction
407    {
408     ncols[0]++;
409     if (maxa==2)
410     {
411      at--;
412      zt--;
413     } 
414     else
415     {
416      ap--;
417      zp--;
418     }
419    }
420    if (rndm>fFracpp && rndm<=(fFracpp+fFracnp)) // n+p interaction
421    {
422     ncols[1]++;
423     if (maxa==2)
424     {
425      at--;
426      zt--;
427     } 
428     else
429     {
430      ap--;
431     }
432    }
433    if (rndm>(fFracpp+fFracnp) && rndm<=(fFracpp+fFracnp+fFracpn)) // p+n interaction
434    {
435     ncols[2]++;
436     if (maxa==2)
437     {
438      at--;
439     } 
440     else
441     {
442      ap--;
443      zp--;
444     }
445    }
446    if (rndm>(fFracpp+fFracnp+fFracpn)) // n+n interaction
447    {
448     ncols[3]++; 
449     if (maxa==2)
450     {
451      at--;
452     } 
453     else
454     {
455      ap--;
456     }
457    }
458   }
459   delete [] rans;
460
461   if (!(fEventnum%fPrintfreq))
462   {
463    cout << " *AliCollider::MakeEvent* Run : " << fRunnum << " Event : " << fEventnum
464         << endl;
465    cout << " npart = " << npt << " ncol = " << ncol 
466         << " ncolpp = " << ncols[0] << " ncolnp = " << ncols[1]
467         << " ncolpn = " << ncols[2] << " ncolnn = " << ncols[3] << endl;
468   }
469
470  }
471
472  if (!fEvent)
473  {
474   fEvent=new AliEvent();
475   fEvent->SetOwner();
476  }
477
478  fEvent->Reset();
479  fEvent->SetRunNumber(fRunnum);
480  fEvent->SetEventNumber(fEventnum);
481
482  AliTrack t;
483  Ali3Vector p;
484  AliPosition r,rx;
485  Float_t v[3];
486  AliVertex vert;
487
488  if (fVertexmode)
489  {
490   // Make sure the primary vertex gets correct location and Id=1
491   v[0]=0;
492   v[1]=0;
493   v[2]=0;
494   r.SetPosition(v,"car");
495   v[0]=fResolution;
496   v[1]=fResolution;
497   v[2]=fResolution;
498   r.SetPositionErrors(v,"car");
499
500   vert.SetId(1);
501   vert.SetTrackCopy(0);
502   vert.SetVertexCopy(0);
503   vert.SetPosition(r);
504   fEvent->AddVertex(vert,0);
505  }
506
507  Int_t kf=0,kc=0;
508  Float_t charge=0,mass=0;
509
510  TMCParticle* part=0;
511
512  Int_t ntypes=4;
513
514  // Singular settings for a normal Pythia elementary particle interation 
515  if (!fNucl)
516  {
517   ntypes=1;
518   ncols[0]=1;
519  }
520
521  // Generate all the various collisions
522  Int_t first=1; // Flag to indicate the first collision process
523  Double_t pnucl;
524  Int_t npart=0,ntk=0;
525  Double_t dist=0;
526  for (Int_t itype=0; itype<ntypes; itype++)
527  {
528   if (fNucl)
529   {
530    if (itype==0 && ncols[itype]) Initialize(fFrame,"p","p",fWin);
531    if (itype==1 && ncols[itype]) Initialize(fFrame,"n","p",fWin);
532    if (itype==2 && ncols[itype]) Initialize(fFrame,"p","n",fWin);
533    if (itype==3 && ncols[itype]) Initialize(fFrame,"n","n",fWin);
534   }
535   for (Int_t jcol=0; jcol<ncols[itype]; jcol++)
536   {
537    GenerateEvent();
538
539    if (first) // Store projectile and target information in the event structure
540    {
541     if (fNucl)
542     {
543      v[0]=GetP(1,1);
544      v[1]=GetP(1,2);
545      v[2]=GetP(1,3);
546      pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
547      fEvent->SetProjectile(fAproj,fZproj,pnucl);
548      v[0]=GetP(2,1);
549      v[1]=GetP(2,2);
550      v[2]=GetP(2,3);
551      pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
552      fEvent->SetTarget(fAtarg,fZtarg,pnucl);
553     }
554     else
555     {
556      v[0]=GetP(1,1);
557      v[1]=GetP(1,2);
558      v[2]=GetP(1,3);
559      pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
560      kf=GetK(1,2);
561      fEvent->SetProjectile(0,0,pnucl,kf);
562      v[0]=GetP(2,1);
563      v[1]=GetP(2,2);
564      v[2]=GetP(2,3);
565      pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
566      kf=GetK(2,2);
567      fEvent->SetTarget(0,0,pnucl,kf);
568     }
569     first=0;
570    }
571
572    if (medit >= 0) Pyedit(medit); // Define which particles are to be kept
573
574    if (mlist >= 0) Pylist(mlist);
575
576    ImportParticles();
577    npart=0;
578    if (fParticles) npart=fParticles->GetEntries();
579
580    for (Int_t jpart=0; jpart<npart; jpart++)
581    {
582     part=(TMCParticle*)fParticles->At(jpart);
583     if (!part) continue;
584
585     kf=part->GetKF();
586     kc=Pycomp(kf);
587
588     charge=GetKCHG(kc,1)/3.;
589     if (kf<0) charge*=-1;
590     mass=GetPMAS(kc,1);
591
592     // 3-momentum in GeV/c
593     v[0]=part->GetPx();
594     v[1]=part->GetPy();
595     v[2]=part->GetPz();
596     p.SetVector(v,"car");
597
598     // Production location in cm.
599     v[0]=(part->GetVx())/10;
600     v[1]=(part->GetVy())/10;
601     v[2]=(part->GetVz())/10;
602     r.SetPosition(v,"car");
603
604     ntk++;
605
606     t.Reset();
607     t.SetId(ntk);
608     t.SetParticleCode(kf);
609     t.SetCharge(charge);
610     t.SetMass(mass);
611     t.Set3Momentum(p);
612     t.SetBeginPoint(r);
613
614     fEvent->AddTrack(t);
615
616     // Build the vertex structures if requested
617     if (fVertexmode)
618     {
619      // Check if track belongs within the resolution to an existing vertex
620      Int_t add=0;  
621      for (Int_t jv=1; jv<=fEvent->GetNvertices(); jv++)
622      {
623       AliVertex* vx=fEvent->GetVertex(jv);
624       if (vx)
625       {
626        rx=vx->GetPosition();
627        dist=rx.GetDistance(r);
628        if (dist < fResolution)
629        {
630         AliTrack* tx=fEvent->GetIdTrack(ntk);
631         if (tx)
632         { 
633          vx->AddTrack(tx);
634          add=1;
635         }
636        }
637       }
638       if (add) break; // No need to look further for vertex candidates
639      }
640
641      // If track was not close enough to an existing vertex
642      // a new secondary vertex is created      
643      if (!add && fVertexmode>1)
644      {
645       AliTrack* tx=fEvent->GetIdTrack(ntk);
646       if (tx)
647       {
648        v[0]=fResolution;
649        v[1]=fResolution;
650        v[2]=fResolution;
651        r.SetPositionErrors(v,"car");
652        vert.Reset();
653        vert.SetTrackCopy(0);
654        vert.SetVertexCopy(0);
655        vert.SetId((fEvent->GetNvertices())+1);
656        vert.SetPosition(r);
657        vert.AddTrack(tx);
658        fEvent->AddVertex(vert,0);
659       } 
660      }
661     }
662    } // End of loop over the produced particles for each collision
663   } // End of loop over number of collisions for each type
664  } // End of loop over collision types
665
666  // Link sec. vertices to primary if requested
667  // Note that also the connecting tracks are automatically created
668  if (fVertexmode>2)
669  {
670   AliVertex* vp=fEvent->GetIdVertex(1); // Primary vertex
671   if (vp)
672   {
673    for (Int_t i=2; i<=fEvent->GetNvertices(); i++)
674    {
675     AliVertex* vx=fEvent->GetVertex(i);
676     if (vx)
677     {
678      if (vx->GetId() != 1) vp->AddVertex(vx);
679     }
680    }
681   }
682  }
683
684  if (mlist) cout << endl; // Create empty output line after the event
685  if (fOutTree) fOutTree->Fill();
686 }
687 ///////////////////////////////////////////////////////////////////////////
688 AliEvent* AliCollider::GetEvent()
689 {
690 // Provide pointer to the generated event structure.
691  return fEvent;
692 }
693 ///////////////////////////////////////////////////////////////////////////
694 void AliCollider::EndRun()
695 {
696 // Properly close the output file (if needed).
697  if (fOutFile)
698  {
699   fOutFile->Write();
700   fOutFile->Close();
701   cout << " *AliCollider::EndRun* Output file correctly closed." << endl;
702  }
703 }
704 ///////////////////////////////////////////////////////////////////////////