]> git.uio.no Git - u/mrichter/AliRoot.git/blame - RALICE/AliCollider.cxx
04-apr-2004 NvE SetMass() invoked from AliTrack::Set3Momentum to get also the energy...
[u/mrichter/AliRoot.git] / RALICE / AliCollider.cxx
CommitLineData
45575004 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
261c0caf 16// $Id: AliCollider.cxx,v 1.11 2004/03/12 09:18:24 nick Exp $
fdbea0ce 17
18///////////////////////////////////////////////////////////////////////////
19// Class AliCollider
20// Pythia based universal physics event generator.
4b570fab 21// This class is derived from TPythia6 and has some extensions to
fdbea0ce 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.
30//
31// For further details concerning the produced output structure,
32// see the docs of the memberfunctions SetVertexMode and SetResolution.
33//
34// Example job of minimum biased Pb+Pb interactions :
35// --------------------------------------------------
36// {
37// gSystem->Load("libEG");
38// gSystem->Load("libEGPythia6");
39// gSystem->Load("ralice");
40//
41// AliCollider* gen=new AliCollider();
42//
43// gen->SetOutputFile("test.root");
44// gen->SetVertexMode(3);
45// gen->SetResolution(1e-4); // 1 micron vertex resolution
46//
47// gen->SetRunNumber(1);
48//
49// Int_t zp=82;
50// Int_t ap=208;
51// Int_t zt=82;
52// Int_t at=208;
53//
54// gen->Init("fixt",zp,ap,zt,at,158);
55//
47dddbe4 56// gen->SetTitle("SPS Pb-Pb collision at 158A GeV/c beam energy");
57//
fdbea0ce 58// Int_t nevents=5;
59//
60// AliRandom rndm;
61// Float_t* rans=new Float_t[nevents];
62// rndm.Uniform(rans,nevents,2,ap+at);
63// Int_t npart;
64// for (Int_t i=0; i<nevents; i++)
65// {
66// npart=rans[i];
67// gen->MakeEvent(npart);
68//
69// AliEvent* evt=gen->GetEvent();
70//
71// evt->List();
72// }
73//
74// gen->EndRun();
75// }
76//
77//
78// Example job of a cosmic nu+p atmospheric interaction.
79// -----------------------------------------------------
80// {
81// gSystem->Load("libEG");
82// gSystem->Load("libEGPythia6");
83// gSystem->Load("ralice");
84//
85// AliCollider* gen=new AliCollider();
86//
87// gen->SetOutputFile("test.root");
88//
89// gen->SetRunNumber(1);
90//
91// gen->Init("fixt","nu_mu","p",1e11);
92//
47dddbe4 93// gen->SetTitle("Atmospheric nu_mu-p interaction at 1e20 eV");
94//
fdbea0ce 95// Int_t nevents=10;
96//
97// for (Int_t i=0; i<nevents; i++)
98// {
99// gen->MakeEvent(0,1);
100//
101// AliEvent* evt=gen->GetEvent();
102//
84bb7c66 103// evt->Data();
fdbea0ce 104// }
105//
106// gen->EndRun();
107// }
108//
109//
110//--- Author: Nick van Eijndhoven 22-nov-2002 Utrecht University
261c0caf 111//- Modified: NvE $Date: 2004/03/12 09:18:24 $ Utrecht University
fdbea0ce 112///////////////////////////////////////////////////////////////////////////
113
114#include "AliCollider.h"
c72198f1 115#include "Riostream.h"
fdbea0ce 116
117ClassImp(AliCollider) // Class implementation to enable ROOT I/O
118
c72198f1 119AliCollider::AliCollider() : TPythia6()
fdbea0ce 120{
121// Default constructor.
122// All variables initialised to default values.
123 fVertexmode=0; // No vertex structure creation
124 fResolution=1e-5; // Standard resolution is 0.1 micron
125 fRunnum=0;
126 fEventnum=0;
127 fPrintfreq=1;
128
129 fEvent=0;
130
47dddbe4 131 fSpecpmin=0;
132
fdbea0ce 133 fFrame="none";
134 fWin=0;
135
136 fNucl=0;
137 fZproj=0;
138 fAproj=0;
139 fZtarg=0;
140 fAtarg=0;
141 fFracpp=0;
142 fFracnp=0;
143 fFracpn=0;
144 fFracnn=0;
145
146 fOutFile=0;
147 fOutTree=0;
47dddbe4 148
149 fSelections=0;
150 fSelect=0;
151
152 TString s=GetName();
153 s+=" (AliCollider)";
154 SetName(s.Data());
fdbea0ce 155}
156///////////////////////////////////////////////////////////////////////////
157AliCollider::~AliCollider()
158{
159// Default destructor
160 if (fEvent)
161 {
162 delete fEvent;
163 fEvent=0;
164 }
165 if (fOutFile)
166 {
167 delete fOutFile;
168 fOutFile=0;
169 }
170 if (fOutTree)
171 {
172 delete fOutTree;
173 fOutTree=0;
174 }
47dddbe4 175 if (fSelections)
176 {
177 delete fSelections;
178 fSelections=0;
179 }
fdbea0ce 180}
181///////////////////////////////////////////////////////////////////////////
182void AliCollider::SetOutputFile(TString s)
183{
184// Create the output file containing all the data in ROOT output format.
185 if (fOutFile)
186 {
187 delete fOutFile;
188 fOutFile=0;
189 }
190 fOutFile=new TFile(s.Data(),"RECREATE","AliCollider data");
191
192 if (fOutTree)
193 {
194 delete fOutTree;
195 fOutTree=0;
196 }
197 fOutTree=new TTree("T","AliCollider event data");
198
199 Int_t bsize=32000;
200 Int_t split=0;
201 fOutTree->Branch("Events","AliEvent",&fEvent,bsize,split);
202}
203///////////////////////////////////////////////////////////////////////////
204void AliCollider::SetVertexMode(Int_t mode)
205{
206// Set the mode of the vertex structure creation.
207//
208// By default all generated tracks will only appear in the AliEvent
209// structure without any primary (and secondary) vertex structure.
210// The user can build the vertex structure if he/she wants by means
211// of the beginpoint location of each AliTrack.
212//
213// However, one can also let AliCollider automatically create
214// the primary (and secondary) vertex structure(s).
215// In this case the primary vertex is given Id=1 and all sec. vertices
216// are given Id's 2,3,4,....
217// All vertices are created as standalone entities in the AliEvent structure
218// without any linking between the various vertices.
219// For this automated process, the user-selected resolution
220// (see SetResolution) is used to decide whether or not certain vertex
221// locations can be resolved.
222// In case no vertex creation is selected (i.e. the default mode=0),
223// the value of the resolution is totally irrelevant.
224//
225// The user can also let AliCollider automatically connect the sec. vertices
226// to the primary vertex (i.e. mode=3). This process will also automatically
227// generate the tracks connecting the vertices.
228// Note that the result of the mode=3 operation may be very sensitive to
229// the resolution parameter. Therefore, no attempt is made to distinguish
230// between secondary, tertiary etc... vertices. All sec. vertices are
231// linked to the primary one.
232//
233// Irrespective of the selected mode, all generated tracks can be obtained
234// directly from the AliEvent structure.
235// In case (sec.) vertex creation is selected, all generated vertices can
236// also be obtained directly from the AliEvent structure.
237// These (sec.) vertices contain only the corresponding pointers to the various
238// tracks which are stored in the AliEvent structure.
239//
240// Overview of vertex creation modes :
241// -----------------------------------
242// mode = 0 ==> No vertex structure will be created
243// 1 ==> Only primary vertex structure will be created
244// 2 ==> Unconnected primary and secondary vertices will be created
245// 3 ==> Primary and secondary vertices will be created where all the
246// sec. vertices will be connected to the primary vertex.
247// Also the vertex connecting tracks will be automatically
248// generated.
249//
250 if (mode<0 || mode >3)
251 {
252 cout << " *AliCollider::SetVertexMode* Invalid argument mode : " << mode << endl;
253 fVertexmode=0;
254 }
255 else
256 {
257 fVertexmode=mode;
258 }
259}
260///////////////////////////////////////////////////////////////////////////
261c0caf 261Int_t AliCollider::GetVertexMode() const
fdbea0ce 262{
263// Provide the current mode for vertex structure creation.
264 return fVertexmode;
265}
266///////////////////////////////////////////////////////////////////////////
267void AliCollider::SetResolution(Double_t res)
268{
269// Set the resolution (in cm) for resolving (sec.) vertices.
270// By default this resolution is set to 0.1 micron.
271// Note : In case no vertex creation has been selected, the value of
272// the resolution is totally irrelevant.
273 fResolution=fabs(res);
274}
275///////////////////////////////////////////////////////////////////////////
261c0caf 276Double_t AliCollider::GetResolution() const
fdbea0ce 277{
278// Provide the current resolution (in cm) for resolving (sec.) vertices.
279 return fResolution;
280}
281///////////////////////////////////////////////////////////////////////////
282void AliCollider::SetRunNumber(Int_t run)
283{
284// Set the user defined run number.
285// By default the run number is set to 0.
286 fRunnum=run;
287}
288///////////////////////////////////////////////////////////////////////////
261c0caf 289Int_t AliCollider::GetRunNumber() const
fdbea0ce 290{
291// Provide the user defined run number.
292 return fRunnum;
293}
294///////////////////////////////////////////////////////////////////////////
295void AliCollider::SetPrintFreq(Int_t n)
296{
297// Set the print frequency for every 'n' events.
298// By default the printfrequency is set to 1 (i.e. every event).
299 fPrintfreq=n;
300}
301///////////////////////////////////////////////////////////////////////////
261c0caf 302Int_t AliCollider::GetPrintFreq() const
fdbea0ce 303{
304// Provide the user selected print frequency.
305 return fPrintfreq;
306}
307///////////////////////////////////////////////////////////////////////////
308void AliCollider::Init(char* frame,char* beam,char* target,Float_t win)
309{
310// Initialisation of the underlying Pythia generator package.
311// This routine just invokes TPythia6::Initialize(...) and the arguments
312// have the corresponding meaning.
313// The event number is reset to 0.
314 fEventnum=0;
315 fNucl=0;
316 fFrame=frame;
317 fWin=win;
318 Initialize(frame,beam,target,win);
c72198f1 319
e313997a 320 cout << endl;
c72198f1 321 cout << " *AliCollider::Init* Standard Pythia initialisation." << endl;
322 cout << " Beam particle : " << beam << " Target particle : " << target
323 << " Frame = " << frame << " Energy = " << win
324 << endl;
fdbea0ce 325}
326///////////////////////////////////////////////////////////////////////////
327void AliCollider::Init(char* frame,Int_t zp,Int_t ap,Int_t zt,Int_t at,Float_t win)
328{
329// Initialisation of the underlying Pythia generator package for the generation
330// of nucleus-nucleus interactions.
331// In addition to the Pythia standard arguments 'frame' and 'win', the user
da17f667 332// can specify here (Z,A) values of the projectile and target nuclei.
333//
334// Note : The 'win' value denotes either the cms energy per nucleon-nucleon collision
335// (i.e. frame="cms") or the momentum per nucleon in all other cases.
336//
fdbea0ce 337// The event number is reset to 0.
338 fEventnum=0;
339 fNucl=1;
340 fFrame=frame;
341 fWin=win;
342 fZproj=0;
343 fAproj=0;
344 fZtarg=0;
345 fAtarg=0;
346 fFracpp=0;
347 fFracnp=0;
348 fFracpn=0;
349 fFracnn=0;
350
351 if (ap<1 || at<1 || zp>ap || zt>at)
352 {
e313997a 353 cout << endl;
fdbea0ce 354 cout << " *AliCollider::Init* Invalid input value(s). Zproj = " << zp
355 << " Aproj = " << ap << " Ztarg = " << zt << " Atarg = " << at << endl;
356 return;
357 }
358
359 fZproj=zp;
360 fAproj=ap;
361 fZtarg=zt;
362 fAtarg=at;
363
e313997a 364 cout << endl;
fdbea0ce 365 cout << " *AliCollider::Init* Nucleus-Nucleus generator initialisation." << endl;
366 cout << " Zproj = " << zp << " Aproj = " << ap << " Ztarg = " << zt << " Atarg = " << at
367 << " Frame = " << frame << " Energy = " << win
368 << endl;
369}
370///////////////////////////////////////////////////////////////////////////
371void AliCollider::GetFractions(Float_t zp,Float_t ap,Float_t zt,Float_t at)
372{
373// Determine the fractions for the various N-N collision processes.
374// The various processes are : p+p, n+p, p+n and n+n.
375 if (zp<0) zp=0;
376 if (zt<0) zt=0;
377
378 fFracpp=0;
379 fFracnp=0;
380 fFracpn=0;
381 fFracnn=0;
382
383 if (ap>0 && at>0)
384 {
385 fFracpp=(zp/ap)*(zt/at);
386 fFracnp=(1.-zp/ap)*(zt/at);
387 fFracpn=(zp/ap)*(1.-zt/at);
388 fFracnn=(1.-zp/ap)*(1.-zt/at);
389 }
390}
391///////////////////////////////////////////////////////////////////////////
392void AliCollider::MakeEvent(Int_t npt,Int_t mlist,Int_t medit)
393{
394// Generate one event.
395// In case of a nucleus-nucleus interaction, the argument 'npt' denotes
396// the number of participant nucleons.
47dddbe4 397// Normally also the spectator tracks will be stored into the event structure.
398// The spectator tracks have a negative user Id to distinguish them from the
399// ordinary generated tracks.
400// In case the user has selected the creation of vertex structures, the spectator
401// tracks will be linked to the primary vertex.
402// However, specification of npt<0 will suppress the storage of spectator tracks.
403// In the latter case abs(npt) will be taken as the number of participants.
fdbea0ce 404// In case of a standard Pythia run for 'elementary' particle interactions,
405// the value of npt is totally irrelevant.
da17f667 406//
fdbea0ce 407// The argument 'mlist' denotes the list mode used for Pylist().
da17f667 408// Note : mlist<0 suppresses the invokation of Pylist().
409// By default, no listing is produced (i.e. mlist=-1).
410//
c72198f1 411// The argument 'medit' denotes the edit mode used for Pyedit().
412// Note : medit<0 suppresses the invokation of Pyedit().
413// By default, only 'stable' final particles are kept (i.e. medit=1).
414//
da17f667 415// In the case of a standard Pythia run concerning 'elementary' particle
416// interactions, the projectile and target particle ID's for the created
417// event structure are set to the corresponding Pythia KF codes.
418// All the A and Z values are in that case set to zero.
419// In case of a nucleus-nucleus interaction, the proper A and Z values for
420// the projectile and target particles are set in the event structure.
421// However, in this case both particle ID's are set to zero.
47dddbe4 422//
423// Note : Only in case an event passed the selection criteria as specified
424// via SelectEvent(), the event will appear on the output file.
fdbea0ce 425
426 fEventnum++;
427
47dddbe4 428 Int_t specmode=1;
429 if (npt<0)
430 {
431 specmode=0;
432 npt=abs(npt);
433 }
434
fdbea0ce 435 // Counters for the various (proj,targ) combinations : p+p, n+p, p+n and n+n
436 Int_t ncols[4]={0,0,0,0};
437
47dddbe4 438 Int_t zp=0;
439 Int_t ap=0;
440 Int_t zt=0;
441 Int_t at=0;
442
c72198f1 443 Int_t ncol=1;
fdbea0ce 444 if (fNucl)
445 {
446 if (npt<1 || npt>(fAproj+fAtarg))
447 {
448 cout << " *AliCollider::MakeEvent* Invalid input value. npt = " << npt
449 << " Aproj = " << fAproj << " Atarg = " << fAtarg << endl;
450 return;
451 }
452
453 // Determine the number of nucleon-nucleon collisions
c72198f1 454 ncol=npt/2;
fdbea0ce 455 if (npt%2 && fRan.Uniform()>0.5) ncol+=1;
456
457 // Determine the number of the various types of N+N interactions
47dddbe4 458 zp=fZproj;
459 ap=fAproj;
460 zt=fZtarg;
461 at=fAtarg;
fdbea0ce 462 Int_t maxa=2; // Indicator whether proj (1) or target (2) has maximal A left
463 if (ap>at) maxa=1;
464 Float_t* rans=new Float_t[ncol];
465 fRan.Uniform(rans,ncol);
466 Float_t rndm=0;
467 for (Int_t i=0; i<ncol; i++)
468 {
469 GetFractions(zp,ap,zt,at);
470 rndm=rans[i];
471 if (rndm<=fFracpp) // p+p interaction
472 {
473 ncols[0]++;
4b570fab 474 if (maxa==2)
fdbea0ce 475 {
476 at--;
477 zt--;
478 }
479 else
480 {
481 ap--;
482 zp--;
483 }
484 }
485 if (rndm>fFracpp && rndm<=(fFracpp+fFracnp)) // n+p interaction
486 {
487 ncols[1]++;
4b570fab 488 if (maxa==2)
fdbea0ce 489 {
490 at--;
491 zt--;
492 }
493 else
494 {
495 ap--;
496 }
497 }
498 if (rndm>(fFracpp+fFracnp) && rndm<=(fFracpp+fFracnp+fFracpn)) // p+n interaction
499 {
500 ncols[2]++;
4b570fab 501 if (maxa==2)
fdbea0ce 502 {
503 at--;
504 }
505 else
506 {
507 ap--;
508 zp--;
509 }
510 }
511 if (rndm>(fFracpp+fFracnp+fFracpn)) // n+n interaction
512 {
513 ncols[3]++;
4b570fab 514 if (maxa==2)
fdbea0ce 515 {
516 at--;
517 }
518 else
519 {
520 ap--;
521 }
522 }
523 }
524 delete [] rans;
c72198f1 525 }
fdbea0ce 526
1c01b4f8 527 if (!(fEventnum%fPrintfreq))
528 {
529 cout << " *AliCollider::MakeEvent* Run : " << fRunnum << " Event : " << fEventnum
530 << endl;
531 if (fNucl)
fdbea0ce 532 {
1c01b4f8 533 cout << " npart = " << npt << " ncol = " << ncol
534 << " ncolpp = " << ncols[0] << " ncolnp = " << ncols[1]
535 << " ncolpn = " << ncols[2] << " ncolnn = " << ncols[3] << endl;
fdbea0ce 536 }
1c01b4f8 537 }
fdbea0ce 538
fdbea0ce 539 if (!fEvent)
540 {
541 fEvent=new AliEvent();
542 fEvent->SetOwner();
47dddbe4 543 fEvent->SetName(GetName());
544 fEvent->SetTitle(GetTitle());
fdbea0ce 545 }
546
547 fEvent->Reset();
548 fEvent->SetRunNumber(fRunnum);
549 fEvent->SetEventNumber(fEventnum);
550
da17f667 551 AliTrack t;
552 Ali3Vector p;
553 AliPosition r,rx;
554 Float_t v[3];
fdbea0ce 555 AliVertex vert;
47dddbe4 556 Ali3Vector pproj,ptarg;
da17f667 557
fdbea0ce 558 if (fVertexmode)
559 {
560 // Make sure the primary vertex gets correct location and Id=1
da17f667 561 v[0]=0;
562 v[1]=0;
563 v[2]=0;
564 r.SetPosition(v,"car");
565 v[0]=fResolution;
566 v[1]=fResolution;
567 v[2]=fResolution;
568 r.SetPositionErrors(v,"car");
569
fdbea0ce 570 vert.SetId(1);
571 vert.SetTrackCopy(0);
572 vert.SetVertexCopy(0);
da17f667 573 vert.SetPosition(r);
fdbea0ce 574 fEvent->AddVertex(vert,0);
575 }
576
c72198f1 577 Int_t kf=0;
fdbea0ce 578 Float_t charge=0,mass=0;
6aff9852 579 TString name;
fdbea0ce 580
fdbea0ce 581 Int_t ntypes=4;
582
583 // Singular settings for a normal Pythia elementary particle interation
584 if (!fNucl)
585 {
586 ntypes=1;
587 ncols[0]=1;
588 }
589
590 // Generate all the various collisions
47dddbe4 591 fSelect=0; // Flag to indicate whether the total event is selected or not
592 Int_t select=0; // Flag to indicate whether the sub-event is selected or not
593 Int_t first=1; // Flag to indicate the first collision process
da17f667 594 Double_t pnucl;
fdbea0ce 595 Int_t npart=0,ntk=0;
596 Double_t dist=0;
597 for (Int_t itype=0; itype<ntypes; itype++)
598 {
599 if (fNucl)
600 {
601 if (itype==0 && ncols[itype]) Initialize(fFrame,"p","p",fWin);
602 if (itype==1 && ncols[itype]) Initialize(fFrame,"n","p",fWin);
603 if (itype==2 && ncols[itype]) Initialize(fFrame,"p","n",fWin);
604 if (itype==3 && ncols[itype]) Initialize(fFrame,"n","n",fWin);
605 }
606 for (Int_t jcol=0; jcol<ncols[itype]; jcol++)
607 {
608 GenerateEvent();
609
47dddbe4 610 select=IsSelected();
611 if (select) fSelect=1;
612
da17f667 613 if (first) // Store projectile and target information in the event structure
614 {
615 if (fNucl)
616 {
617 v[0]=GetP(1,1);
618 v[1]=GetP(1,2);
619 v[2]=GetP(1,3);
47dddbe4 620 pproj.SetVector(v,"car");
621 pnucl=pproj.GetNorm();
da17f667 622 fEvent->SetProjectile(fAproj,fZproj,pnucl);
623 v[0]=GetP(2,1);
624 v[1]=GetP(2,2);
625 v[2]=GetP(2,3);
47dddbe4 626 ptarg.SetVector(v,"car");
627 pnucl=ptarg.GetNorm();
da17f667 628 fEvent->SetTarget(fAtarg,fZtarg,pnucl);
629 }
630 else
631 {
632 v[0]=GetP(1,1);
633 v[1]=GetP(1,2);
634 v[2]=GetP(1,3);
635 pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
636 kf=GetK(1,2);
637 fEvent->SetProjectile(0,0,pnucl,kf);
638 v[0]=GetP(2,1);
639 v[1]=GetP(2,2);
640 v[2]=GetP(2,3);
641 pnucl=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
642 kf=GetK(2,2);
643 fEvent->SetTarget(0,0,pnucl,kf);
644 }
645 first=0;
646 }
647
648 if (medit >= 0) Pyedit(medit); // Define which particles are to be kept
fdbea0ce 649
47dddbe4 650 if (mlist>=0 && select) Pylist(mlist);
fdbea0ce 651
c72198f1 652 npart=GetN();
653 for (Int_t jpart=1; jpart<=npart; jpart++)
fdbea0ce 654 {
c72198f1 655 kf=GetK(jpart,2);
656 charge=Pychge(kf)/3.;
657 mass=GetP(jpart,5);
6aff9852 658 name=GetPyname(kf);
fdbea0ce 659
660 // 3-momentum in GeV/c
c72198f1 661 v[0]=GetP(jpart,1);
662 v[1]=GetP(jpart,2);
663 v[2]=GetP(jpart,3);
fdbea0ce 664 p.SetVector(v,"car");
665
666 // Production location in cm.
c72198f1 667 v[0]=GetV(jpart,1)/10;
668 v[1]=GetV(jpart,2)/10;
669 v[2]=GetV(jpart,3)/10;
da17f667 670 r.SetPosition(v,"car");
fdbea0ce 671
672 ntk++;
673
674 t.Reset();
675 t.SetId(ntk);
676 t.SetParticleCode(kf);
6aff9852 677 t.SetName(name.Data());
fdbea0ce 678 t.SetCharge(charge);
679 t.SetMass(mass);
680 t.Set3Momentum(p);
681 t.SetBeginPoint(r);
682
683 fEvent->AddTrack(t);
684
685 // Build the vertex structures if requested
686 if (fVertexmode)
687 {
688 // Check if track belongs within the resolution to an existing vertex
689 Int_t add=0;
690 for (Int_t jv=1; jv<=fEvent->GetNvertices(); jv++)
691 {
692 AliVertex* vx=fEvent->GetVertex(jv);
693 if (vx)
694 {
695 rx=vx->GetPosition();
696 dist=rx.GetDistance(r);
697 if (dist < fResolution)
698 {
699 AliTrack* tx=fEvent->GetIdTrack(ntk);
700 if (tx)
701 {
702 vx->AddTrack(tx);
703 add=1;
704 }
705 }
706 }
707 if (add) break; // No need to look further for vertex candidates
708 }
709
710 // If track was not close enough to an existing vertex
711 // a new secondary vertex is created
712 if (!add && fVertexmode>1)
713 {
714 AliTrack* tx=fEvent->GetIdTrack(ntk);
715 if (tx)
716 {
da17f667 717 v[0]=fResolution;
718 v[1]=fResolution;
719 v[2]=fResolution;
720 r.SetPositionErrors(v,"car");
fdbea0ce 721 vert.Reset();
722 vert.SetTrackCopy(0);
723 vert.SetVertexCopy(0);
724 vert.SetId((fEvent->GetNvertices())+1);
725 vert.SetPosition(r);
726 vert.AddTrack(tx);
727 fEvent->AddVertex(vert,0);
728 }
729 }
730 }
731 } // End of loop over the produced particles for each collision
732 } // End of loop over number of collisions for each type
733 } // End of loop over collision types
734
735 // Link sec. vertices to primary if requested
736 // Note that also the connecting tracks are automatically created
737 if (fVertexmode>2)
738 {
739 AliVertex* vp=fEvent->GetIdVertex(1); // Primary vertex
740 if (vp)
741 {
742 for (Int_t i=2; i<=fEvent->GetNvertices(); i++)
743 {
744 AliVertex* vx=fEvent->GetVertex(i);
745 if (vx)
746 {
747 if (vx->GetId() != 1) vp->AddVertex(vx);
748 }
749 }
750 }
751 }
752
47dddbe4 753 // Include the spectator tracks in the event structure.
754 if (fNucl && specmode)
755 {
47dddbe4 756 v[0]=0;
757 v[1]=0;
758 v[2]=0;
759 r.SetPosition(v,"car");
760
761 zp=fZproj-(ncols[0]+ncols[2]);
762 if (zp<0) zp=0;
763 ap=fAproj-(ncols[0]+ncols[1]+ncols[2]+ncols[3]);
764 if (ap<0) ap=0;
765 zt=fZtarg-(ncols[0]+ncols[1]);
766 if (zt<0) zt=0;
767 at=fAtarg-(ncols[0]+ncols[1]+ncols[2]+ncols[3]);
768 if (at<0) at=0;
769
770 Int_t nspec=0;
771
772 if (pproj.GetNorm() > fSpecpmin)
773 {
774 kf=2212; // Projectile spectator protons
775 charge=Pychge(kf)/3.;
6aff9852 776 mass=GetPMAS(Pycomp(kf),1);
777 name=GetPyname(kf);
47dddbe4 778 for (Int_t iprojp=1; iprojp<=zp; iprojp++)
779 {
780 nspec++;
781 t.Reset();
782 t.SetId(-nspec);
783 t.SetParticleCode(kf);
6aff9852 784 t.SetName(name.Data());
47dddbe4 785 t.SetTitle("Projectile spectator proton");
786 t.SetCharge(charge);
787 t.SetMass(mass);
788 t.Set3Momentum(pproj);
789 t.SetBeginPoint(r);
790
791 fEvent->AddTrack(t);
792 }
793
794 kf=2112; // Projectile spectator neutrons
795 charge=Pychge(kf)/3.;
6aff9852 796 mass=GetPMAS(Pycomp(kf),1);
797 name=GetPyname(kf);
47dddbe4 798 for (Int_t iprojn=1; iprojn<=(ap-zp); iprojn++)
799 {
800 nspec++;
801 t.Reset();
802 t.SetId(-nspec);
803 t.SetParticleCode(kf);
6aff9852 804 t.SetName(name.Data());
47dddbe4 805 t.SetTitle("Projectile spectator neutron");
806 t.SetCharge(charge);
807 t.SetMass(mass);
808 t.Set3Momentum(pproj);
809 t.SetBeginPoint(r);
810
811 fEvent->AddTrack(t);
812 }
813 }
814
815 if (ptarg.GetNorm() > fSpecpmin)
816 {
817 kf=2212; // Target spectator protons
818 charge=Pychge(kf)/3.;
6aff9852 819 mass=GetPMAS(Pycomp(kf),1);
820 name=GetPyname(kf);
47dddbe4 821 for (Int_t itargp=1; itargp<=zt; itargp++)
822 {
823 nspec++;
824 t.Reset();
825 t.SetId(-nspec);
826 t.SetParticleCode(kf);
6aff9852 827 t.SetName(name.Data());
47dddbe4 828 t.SetTitle("Target spectator proton");
829 t.SetCharge(charge);
830 t.SetMass(mass);
831 t.Set3Momentum(ptarg);
832 t.SetBeginPoint(r);
833
834 fEvent->AddTrack(t);
835 }
836
837 kf=2112; // Target spectator neutrons
838 charge=Pychge(kf)/3.;
6aff9852 839 mass=GetPMAS(Pycomp(kf),1);
840 name=GetPyname(kf);
47dddbe4 841 for (Int_t itargn=1; itargn<=(at-zt); itargn++)
842 {
843 nspec++;
844 t.Reset();
845 t.SetId(-nspec);
846 t.SetParticleCode(kf);
6aff9852 847 t.SetName(name.Data());
47dddbe4 848 t.SetTitle("Target spectator neutron");
849 t.SetCharge(charge);
850 t.SetMass(mass);
851 t.Set3Momentum(ptarg);
852 t.SetBeginPoint(r);
853
854 fEvent->AddTrack(t);
855 }
856 }
857
858 // Link the spectator tracks to the primary vertex.
859 if (fVertexmode)
860 {
861 AliVertex* vp=fEvent->GetIdVertex(1);
862 if (vp)
863 {
864 for (Int_t ispec=1; ispec<=nspec; ispec++)
865 {
866 AliTrack* tx=fEvent->GetIdTrack(-ispec);
867 if (tx) vp->AddTrack(tx);
868 }
869 }
870 }
871}
872
c72198f1 873 if (mlist && !(fEventnum%fPrintfreq)) cout << endl; // Create empty output line after the event
47dddbe4 874
875 if (fOutTree && fSelect) fOutTree->Fill();
fdbea0ce 876}
877///////////////////////////////////////////////////////////////////////////
261c0caf 878AliEvent* AliCollider::GetEvent(Int_t select) const
fdbea0ce 879{
880// Provide pointer to the generated event structure.
47dddbe4 881//
882// select = 0 : Always return the pointer to the generated event.
883// 1 : Only return the pointer to the generated event in case
884// the event passed the selection criteria as specified via
885// SelectEvent(). Otherwise the value 0 will be returned.
886//
887// By invoking GetEvent() the default of select=0 will be used.
888
889 if (!select || fSelect)
890 {
891 return fEvent;
892 }
893 else
894 {
895 return 0;
896 }
fdbea0ce 897}
898///////////////////////////////////////////////////////////////////////////
899void AliCollider::EndRun()
900{
901// Properly close the output file (if needed).
902 if (fOutFile)
903 {
904 fOutFile->Write();
905 fOutFile->Close();
906 cout << " *AliCollider::EndRun* Output file correctly closed." << endl;
907 }
908}
909///////////////////////////////////////////////////////////////////////////
5f25234b 910void AliCollider::SetStable(Int_t id,Int_t mode)
911{
912// Declare whether a particle must be regarded as stable or not.
913// The parameter "id" indicates the Pythia KF particle code, which
914// basically is the PDG particle identifier code.
915// The parameter "mode" indicates the action to be taken.
916//
917// mode = 0 : Particle will be able to decay
918// 1 : Particle will be regarded as stable.
919//
920// In case the user does NOT explicitly invoke this function, the standard
921// Pythia settings for the decay tables are used.
922//
923// When this function is invoked without the "mode" argument, then the
924// default of mode=1 will be used for the specified particle.
925//
926// Notes :
927// -------
928// 1) This function should be invoked after the initialisation call
929// to AliCollider::Init.
930// 2) Due to the internals of Pythia, there is no need to specify particles
931// and their corresponding anti-particles separately as (un)stable.
932// Once a particle has been declared (un)stable, the corresponding
933// anti-particle will be treated in the same way.
934
935 if (mode==0 || mode==1)
936 {
937 Int_t kc=Pycomp(id);
938 Int_t decay=1-mode;
939 if (kc>0)
940 {
941 SetMDCY(kc,1,decay);
942 }
943 else
944 {
945 cout << " *AliCollider::SetStable* Unknown particle code. id = " << id << endl;
946 }
947 }
948 else
949 {
950 cout << " *AliCollider::SetStable* Invalid parameter. mode = " << mode << endl;
951 }
952}
953///////////////////////////////////////////////////////////////////////////
47dddbe4 954void AliCollider::SelectEvent(Int_t id)
955{
956// Add a particle to the event selection list.
957// The parameter "id" indicates the Pythia KF particle code, which
958// basically is the PDG particle identifier code.
959// In case the user has built a selection list via this procedure, only the
960// events in which one of the particles specified in the list was generated
961// will be kept.
962// The investigation of the generated particles takes place when the complete
963// event is in memory, including all (shortlived) mother particles and resonances.
964// So, the settings of the various particle decay modes have no influence on
965// the event selection described here.
966//
967// If no list has been specified, all events will be accepted.
968//
969// Note : id=0 will delete the selection list.
970//
971// Be aware of the fact that severe selection criteria (i.e. selecting only
972// rare events) may result in long runtimes before an event sample has been
973// obtained.
974//
975 if (!id)
976 {
977 if (fSelections)
978 {
979 delete fSelections;
980 fSelections=0;
981 }
982 }
983 else
984 {
985 Int_t kc=Pycomp(id);
986 if (!fSelections)
987 {
988 fSelections=new TArrayI(1);
989 fSelections->AddAt(kc,0);
990 }
991 else
992 {
993 Int_t exist=0;
994 Int_t size=fSelections->GetSize();
995 for (Int_t i=0; i<size; i++)
996 {
997 if (kc==fSelections->At(i))
998 {
999 exist=1;
1000 break;
1001 }
1002 }
1003
1004 if (!exist)
1005 {
1006 fSelections->Set(size+1);
1007 fSelections->AddAt(kc,size);
1008 }
1009 }
1010 }
1011}
1012///////////////////////////////////////////////////////////////////////////
261c0caf 1013Int_t AliCollider::GetSelectionFlag() const
47dddbe4 1014{
1015// Return the value of the selection flag for the total event.
1016// When the event passed the selection criteria as specified via
1017// SelectEvent() the value 1 is returned, otherwise the value 0 is returned.
1018 return fSelect;
1019}
1020///////////////////////////////////////////////////////////////////////////
1021Int_t AliCollider::IsSelected()
1022{
1023// Check whether the generated (sub)event contains one of the particles
1024// specified in the selection list via SelectEvent().
1025// If this is the case or when no selection list is present, the value 1
1026// will be returned, indicating the event is selected to be kept.
1027// Otherwise the value 0 will be returned.
1028
1029 if (!fSelections) return 1;
1030
1031 Int_t nsel=fSelections->GetSize();
1032 Int_t npart=GetN();
1033 Int_t kf,kc;
1034
1035 Int_t select=0;
1036 for (Int_t jpart=1; jpart<=npart; jpart++)
1037 {
1038 kf=GetK(jpart,2);
1039 kc=Pycomp(kf);
1040 for (Int_t i=0; i<nsel; i++)
1041 {
1042 if (kc==fSelections->At(i))
1043 {
1044 select=1;
1045 break;
1046 }
1047 }
1048 if (select) break;
1049 }
1050 return select;
1051}
1052///////////////////////////////////////////////////////////////////////////
1053void AliCollider::SetSpectatorPmin(Float_t pmin)
1054{
1055// Set minimal momentum in GeV/c for spectator tracks to be stored.
1056// Spectator tracks with a momentum below this threshold will not be stored
1057// in the (output) event structure.
1058// This facility allows to minimise the output file size.
1059// Note that when the user wants to boost the event into another reference
1060// frame these spectator tracks might have got momenta above the threshold.
1061// However, when the spectator tracks were not stored in the event structure
1062// in the original frame, there is no way to retreive them anymore.
1063 fSpecpmin=pmin;
1064}
1065///////////////////////////////////////////////////////////////////////////
261c0caf 1066Float_t AliCollider::GetSpectatorPmin() const
47dddbe4 1067{
1068// Provide the minimal spectator momentum in GeV/c.
1069 return fSpecpmin;
1070}
1071///////////////////////////////////////////////////////////////////////////
6aff9852 1072TString AliCollider::GetPyname(Int_t kf)
1073{
1074// Provide the correctly truncated Pythia particle name for PGD code kf
1075//
1076// The TPythia6::Pyname returned name is copied into a TString and truncated
1077// at the first blank to prevent funny trailing characters due to incorrect
1078// stripping of empty characters in TPythia6::Pyname.
1079// The truncation at the first blank is allowed due to the Pythia convention
1080// that particle names never contain blanks.
1081 char name[16];
1082 TString sname;
1083 Pyname(kf,name);
1084 sname=name[0];
1085 for (Int_t i=1; i<16; i++)
1086 {
1087 if (name[i]==' ') break;
1088 sname=sname+name[i];
1089 }
1090 return sname;
1091}
1092///////////////////////////////////////////////////////////////////////////