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