1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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 **************************************************************************/
16 // $Id: AliCollider.cxx,v 1.6 2003/08/29 09:05:11 nick Exp $
18 ///////////////////////////////////////////////////////////////////////////
20 // Pythia based universal physics event generator.
21 // This class is derived from TPythia6 and has some extensions to
22 // support also generation of nucleus-nucleus interactions and to allow
23 // investigation of the effect of detector resolving power.
24 // Furthermore, the produced event information is provided in a format
25 // using the AliEvent structure.
26 // For the produced AliTrack objects, the particle ID code is set to the
27 // Pythia KF value, which is compatible with the PDG identifier.
28 // This will allow a direct analysis of the produced data using the
29 // Ralice physics analysis tools.
31 // For further details concerning the produced output structure,
32 // see the docs of the memberfunctions SetVertexMode and SetResolution.
34 // Example job of minimum biased Pb+Pb interactions :
35 // --------------------------------------------------
37 // gSystem->Load("libEG");
38 // gSystem->Load("libEGPythia6");
39 // gSystem->Load("ralice");
41 // AliCollider* gen=new AliCollider();
43 // gen->SetOutputFile("test.root");
44 // gen->SetVertexMode(3);
45 // gen->SetResolution(1e-4); // 1 micron vertex resolution
47 // gen->SetRunNumber(1);
54 // gen->Init("fixt",zp,ap,zt,at,158);
59 // Float_t* rans=new Float_t[nevents];
60 // rndm.Uniform(rans,nevents,2,ap+at);
62 // for (Int_t i=0; i<nevents; i++)
65 // gen->MakeEvent(npart);
67 // AliEvent* evt=gen->GetEvent();
76 // Example job of a cosmic nu+p atmospheric interaction.
77 // -----------------------------------------------------
79 // gSystem->Load("libEG");
80 // gSystem->Load("libEGPythia6");
81 // gSystem->Load("ralice");
83 // AliCollider* gen=new AliCollider();
85 // gen->SetOutputFile("test.root");
87 // gen->SetRunNumber(1);
89 // gen->Init("fixt","nu_mu","p",1e11);
93 // for (Int_t i=0; i<nevents; i++)
95 // gen->MakeEvent(0,1);
97 // AliEvent* evt=gen->GetEvent();
106 //--- Author: Nick van Eijndhoven 22-nov-2002 Utrecht University
107 //- Modified: NvE $Date: 2003/08/29 09:05:11 $ Utrecht University
108 ///////////////////////////////////////////////////////////////////////////
110 #include "AliCollider.h"
111 #include "Riostream.h"
113 ClassImp(AliCollider) // Class implementation to enable ROOT I/O
115 AliCollider::AliCollider() : TPythia6()
117 // Default constructor.
118 // All variables initialised to default values.
119 fVertexmode=0; // No vertex structure creation
120 fResolution=1e-5; // Standard resolution is 0.1 micron
143 ///////////////////////////////////////////////////////////////////////////
144 AliCollider::~AliCollider()
146 // Default destructor
163 ///////////////////////////////////////////////////////////////////////////
164 void AliCollider::SetOutputFile(TString s)
166 // Create the output file containing all the data in ROOT output format.
172 fOutFile=new TFile(s.Data(),"RECREATE","AliCollider data");
179 fOutTree=new TTree("T","AliCollider event data");
183 fOutTree->Branch("Events","AliEvent",&fEvent,bsize,split);
185 ///////////////////////////////////////////////////////////////////////////
186 void AliCollider::SetVertexMode(Int_t mode)
188 // Set the mode of the vertex structure creation.
190 // By default all generated tracks will only appear in the AliEvent
191 // structure without any primary (and secondary) vertex structure.
192 // The user can build the vertex structure if he/she wants by means
193 // of the beginpoint location of each AliTrack.
195 // However, one can also let AliCollider automatically create
196 // the primary (and secondary) vertex structure(s).
197 // In this case the primary vertex is given Id=1 and all sec. vertices
198 // are given Id's 2,3,4,....
199 // All vertices are created as standalone entities in the AliEvent structure
200 // without any linking between the various vertices.
201 // For this automated process, the user-selected resolution
202 // (see SetResolution) is used to decide whether or not certain vertex
203 // locations can be resolved.
204 // In case no vertex creation is selected (i.e. the default mode=0),
205 // the value of the resolution is totally irrelevant.
207 // The user can also let AliCollider automatically connect the sec. vertices
208 // to the primary vertex (i.e. mode=3). This process will also automatically
209 // generate the tracks connecting the vertices.
210 // Note that the result of the mode=3 operation may be very sensitive to
211 // the resolution parameter. Therefore, no attempt is made to distinguish
212 // between secondary, tertiary etc... vertices. All sec. vertices are
213 // linked to the primary one.
215 // Irrespective of the selected mode, all generated tracks can be obtained
216 // directly from the AliEvent structure.
217 // In case (sec.) vertex creation is selected, all generated vertices can
218 // also be obtained directly from the AliEvent structure.
219 // These (sec.) vertices contain only the corresponding pointers to the various
220 // tracks which are stored in the AliEvent structure.
222 // Overview of vertex creation modes :
223 // -----------------------------------
224 // mode = 0 ==> No vertex structure will be created
225 // 1 ==> Only primary vertex structure will be created
226 // 2 ==> Unconnected primary and secondary vertices will be created
227 // 3 ==> Primary and secondary vertices will be created where all the
228 // sec. vertices will be connected to the primary vertex.
229 // Also the vertex connecting tracks will be automatically
232 if (mode<0 || mode >3)
234 cout << " *AliCollider::SetVertexMode* Invalid argument mode : " << mode << endl;
242 ///////////////////////////////////////////////////////////////////////////
243 Int_t AliCollider::GetVertexMode()
245 // Provide the current mode for vertex structure creation.
248 ///////////////////////////////////////////////////////////////////////////
249 void AliCollider::SetResolution(Double_t res)
251 // Set the resolution (in cm) for resolving (sec.) vertices.
252 // By default this resolution is set to 0.1 micron.
253 // Note : In case no vertex creation has been selected, the value of
254 // the resolution is totally irrelevant.
255 fResolution=fabs(res);
257 ///////////////////////////////////////////////////////////////////////////
258 Double_t AliCollider::GetResolution()
260 // Provide the current resolution (in cm) for resolving (sec.) vertices.
263 ///////////////////////////////////////////////////////////////////////////
264 void AliCollider::SetRunNumber(Int_t run)
266 // Set the user defined run number.
267 // By default the run number is set to 0.
270 ///////////////////////////////////////////////////////////////////////////
271 Int_t AliCollider::GetRunNumber()
273 // Provide the user defined run number.
276 ///////////////////////////////////////////////////////////////////////////
277 void AliCollider::SetPrintFreq(Int_t n)
279 // Set the print frequency for every 'n' events.
280 // By default the printfrequency is set to 1 (i.e. every event).
283 ///////////////////////////////////////////////////////////////////////////
284 Int_t AliCollider::GetPrintFreq()
286 // Provide the user selected print frequency.
289 ///////////////////////////////////////////////////////////////////////////
290 void AliCollider::Init(char* frame,char* beam,char* target,Float_t win)
292 // Initialisation of the underlying Pythia generator package.
293 // This routine just invokes TPythia6::Initialize(...) and the arguments
294 // have the corresponding meaning.
295 // The event number is reset to 0.
300 Initialize(frame,beam,target,win);
302 cout << " *AliCollider::Init* Standard Pythia initialisation." << endl;
303 cout << " Beam particle : " << beam << " Target particle : " << target
304 << " Frame = " << frame << " Energy = " << win
307 ///////////////////////////////////////////////////////////////////////////
308 void AliCollider::Init(char* frame,Int_t zp,Int_t ap,Int_t zt,Int_t at,Float_t win)
310 // Initialisation of the underlying Pythia generator package for the generation
311 // of nucleus-nucleus interactions.
312 // In addition to the Pythia standard arguments 'frame' and 'win', the user
313 // can specify here (Z,A) values of the projectile and target nuclei.
315 // Note : The 'win' value denotes either the cms energy per nucleon-nucleon collision
316 // (i.e. frame="cms") or the momentum per nucleon in all other cases.
318 // The event number is reset to 0.
332 if (ap<1 || at<1 || zp>ap || zt>at)
334 cout << " *AliCollider::Init* Invalid input value(s). Zproj = " << zp
335 << " Aproj = " << ap << " Ztarg = " << zt << " Atarg = " << at << endl;
344 cout << " *AliCollider::Init* Nucleus-Nucleus generator initialisation." << endl;
345 cout << " Zproj = " << zp << " Aproj = " << ap << " Ztarg = " << zt << " Atarg = " << at
346 << " Frame = " << frame << " Energy = " << win
349 ///////////////////////////////////////////////////////////////////////////
350 void AliCollider::GetFractions(Float_t zp,Float_t ap,Float_t zt,Float_t at)
352 // Determine the fractions for the various N-N collision processes.
353 // The various processes are : p+p, n+p, p+n and n+n.
364 fFracpp=(zp/ap)*(zt/at);
365 fFracnp=(1.-zp/ap)*(zt/at);
366 fFracpn=(zp/ap)*(1.-zt/at);
367 fFracnn=(1.-zp/ap)*(1.-zt/at);
370 ///////////////////////////////////////////////////////////////////////////
371 void AliCollider::MakeEvent(Int_t npt,Int_t mlist,Int_t medit)
373 // Generate one event.
374 // In case of a nucleus-nucleus interaction, the argument 'npt' denotes
375 // the number of participant nucleons.
376 // In case of a standard Pythia run for 'elementary' particle interactions,
377 // the value of npt is totally irrelevant.
379 // The argument 'mlist' denotes the list mode used for Pylist().
380 // Note : mlist<0 suppresses the invokation of Pylist().
381 // By default, no listing is produced (i.e. mlist=-1).
383 // The argument 'medit' denotes the edit mode used for Pyedit().
384 // Note : medit<0 suppresses the invokation of Pyedit().
385 // By default, only 'stable' final particles are kept (i.e. medit=1).
387 // In the case of a standard Pythia run concerning 'elementary' particle
388 // interactions, the projectile and target particle ID's for the created
389 // event structure are set to the corresponding Pythia KF codes.
390 // All the A and Z values are in that case set to zero.
391 // In case of a nucleus-nucleus interaction, the proper A and Z values for
392 // the projectile and target particles are set in the event structure.
393 // However, in this case both particle ID's are set to zero.
397 // Counters for the various (proj,targ) combinations : p+p, n+p, p+n and n+n
398 Int_t ncols[4]={0,0,0,0};
403 if (npt<1 || npt>(fAproj+fAtarg))
405 cout << " *AliCollider::MakeEvent* Invalid input value. npt = " << npt
406 << " Aproj = " << fAproj << " Atarg = " << fAtarg << endl;
410 // Determine the number of nucleon-nucleon collisions
412 if (npt%2 && fRan.Uniform()>0.5) ncol+=1;
414 // Determine the number of the various types of N+N interactions
419 Int_t maxa=2; // Indicator whether proj (1) or target (2) has maximal A left
421 Float_t* rans=new Float_t[ncol];
422 fRan.Uniform(rans,ncol);
424 for (Int_t i=0; i<ncol; i++)
426 GetFractions(zp,ap,zt,at);
428 if (rndm<=fFracpp) // p+p interaction
442 if (rndm>fFracpp && rndm<=(fFracpp+fFracnp)) // n+p interaction
455 if (rndm>(fFracpp+fFracnp) && rndm<=(fFracpp+fFracnp+fFracpn)) // p+n interaction
468 if (rndm>(fFracpp+fFracnp+fFracpn)) // n+n interaction
484 if (!(fEventnum%fPrintfreq))
486 cout << " *AliCollider::MakeEvent* Run : " << fRunnum << " Event : " << fEventnum
490 cout << " npart = " << npt << " ncol = " << ncol
491 << " ncolpp = " << ncols[0] << " ncolnp = " << ncols[1]
492 << " ncolpn = " << ncols[2] << " ncolnn = " << ncols[3] << endl;
498 fEvent=new AliEvent();
503 fEvent->SetRunNumber(fRunnum);
504 fEvent->SetEventNumber(fEventnum);
514 // Make sure the primary vertex gets correct location and Id=1
518 r.SetPosition(v,"car");
522 r.SetPositionErrors(v,"car");
525 vert.SetTrackCopy(0);
526 vert.SetVertexCopy(0);
528 fEvent->AddVertex(vert,0);
532 Float_t charge=0,mass=0;
536 // Singular settings for a normal Pythia elementary particle interation
543 // Generate all the various collisions
544 Int_t first=1; // Flag to indicate the first collision process
548 for (Int_t itype=0; itype<ntypes; itype++)
552 if (itype==0 && ncols[itype]) Initialize(fFrame,"p","p",fWin);
553 if (itype==1 && ncols[itype]) Initialize(fFrame,"n","p",fWin);
554 if (itype==2 && ncols[itype]) Initialize(fFrame,"p","n",fWin);
555 if (itype==3 && ncols[itype]) Initialize(fFrame,"n","n",fWin);
557 for (Int_t jcol=0; jcol<ncols[itype]; jcol++)
561 if (first) // Store projectile and target information in the event structure
568 pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
569 fEvent->SetProjectile(fAproj,fZproj,pnucl);
573 pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
574 fEvent->SetTarget(fAtarg,fZtarg,pnucl);
581 pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
583 fEvent->SetProjectile(0,0,pnucl,kf);
587 pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
589 fEvent->SetTarget(0,0,pnucl,kf);
594 if (medit >= 0) Pyedit(medit); // Define which particles are to be kept
596 if (mlist >= 0) Pylist(mlist);
599 for (Int_t jpart=1; jpart<=npart; jpart++)
602 charge=Pychge(kf)/3.;
605 // 3-momentum in GeV/c
609 p.SetVector(v,"car");
611 // Production location in cm.
612 v[0]=GetV(jpart,1)/10;
613 v[1]=GetV(jpart,2)/10;
614 v[2]=GetV(jpart,3)/10;
615 r.SetPosition(v,"car");
621 t.SetParticleCode(kf);
629 // Build the vertex structures if requested
632 // Check if track belongs within the resolution to an existing vertex
634 for (Int_t jv=1; jv<=fEvent->GetNvertices(); jv++)
636 AliVertex* vx=fEvent->GetVertex(jv);
639 rx=vx->GetPosition();
640 dist=rx.GetDistance(r);
641 if (dist < fResolution)
643 AliTrack* tx=fEvent->GetIdTrack(ntk);
651 if (add) break; // No need to look further for vertex candidates
654 // If track was not close enough to an existing vertex
655 // a new secondary vertex is created
656 if (!add && fVertexmode>1)
658 AliTrack* tx=fEvent->GetIdTrack(ntk);
664 r.SetPositionErrors(v,"car");
666 vert.SetTrackCopy(0);
667 vert.SetVertexCopy(0);
668 vert.SetId((fEvent->GetNvertices())+1);
671 fEvent->AddVertex(vert,0);
675 } // End of loop over the produced particles for each collision
676 } // End of loop over number of collisions for each type
677 } // End of loop over collision types
679 // Link sec. vertices to primary if requested
680 // Note that also the connecting tracks are automatically created
683 AliVertex* vp=fEvent->GetIdVertex(1); // Primary vertex
686 for (Int_t i=2; i<=fEvent->GetNvertices(); i++)
688 AliVertex* vx=fEvent->GetVertex(i);
691 if (vx->GetId() != 1) vp->AddVertex(vx);
697 if (mlist && !(fEventnum%fPrintfreq)) cout << endl; // Create empty output line after the event
698 if (fOutTree) fOutTree->Fill();
700 ///////////////////////////////////////////////////////////////////////////
701 AliEvent* AliCollider::GetEvent()
703 // Provide pointer to the generated event structure.
706 ///////////////////////////////////////////////////////////////////////////
707 void AliCollider::EndRun()
709 // Properly close the output file (if needed).
714 cout << " *AliCollider::EndRun* Output file correctly closed." << endl;
717 ///////////////////////////////////////////////////////////////////////////