275c95bd94d28e44dd76fb9281cc15739d09dbbb
[u/mrichter/AliRoot.git] / STEER / AliRun.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /*
17 $Log$
18 Revision 1.66  2001/05/22 14:32:40  hristov
19 Weird inline removed
20
21 Revision 1.65  2001/05/21 17:22:51  buncic
22 Fixed problem with missing AliConfig while reading galice.root
23
24 Revision 1.64  2001/05/16 14:57:22  alibrary
25 New files for folders and Stack
26
27 Revision 1.62  2001/04/06 11:12:33  morsch
28 Clear fParticles after each event. (Ivana Hrivnacova)
29
30 Revision 1.61  2001/03/30 07:04:10  morsch
31 Call fGenerator->FinishRun() for final print-outs, cross-section and weight calculations.
32
33 Revision 1.60  2001/03/21 18:22:30  hristov
34 fParticleFileMap fix (I.Hrivnacova)
35
36 Revision 1.59  2001/03/12 17:47:03  hristov
37 Changes needed on Sun with CC 5.0
38
39 Revision 1.58  2001/03/09 14:27:26  morsch
40 Fix for multiple events per file: inhibit decrease of size of  fParticleFileMap.
41
42 Revision 1.57  2001/02/23 17:40:23  buncic
43 All trees needed for simulation created in RunMC(). TreeR and its branches
44 are now created in new RunReco() method.
45
46 Revision 1.56  2001/02/14 15:45:20  hristov
47 Algorithmic way of getting entry index in fParticleMap. Protection of fParticleFileMap (I.Hrivnacova)
48
49 Revision 1.55  2001/02/12 15:52:54  buncic
50 Removed OpenBaseFile().
51
52 Revision 1.54  2001/02/07 10:39:05  hristov
53 Remove default value for argument
54
55 Revision 1.53  2001/02/06 11:02:26  hristov
56 New SetTrack interface added, added check for unfilled particles in FinishEvent (I.Hrivnacova)
57
58 Revision 1.52  2001/02/05 16:22:25  buncic
59 Added TreeS to GetEvent().
60
61 Revision 1.51  2001/02/02 15:16:20  morsch
62 SetHighWaterMark method added to mark last particle in event.
63
64 Revision 1.50  2001/01/27 10:32:00  hristov
65 Leave the loop when primaries are filled (I.Hrivnacova)
66
67 Revision 1.49  2001/01/26 19:58:48  hristov
68 Major upgrade of AliRoot code
69
70 Revision 1.48  2001/01/17 10:50:50  hristov
71 Corrections to destructors
72
73 Revision 1.47  2000/12/18 10:44:01  morsch
74 Possibility to set field map by passing pointer to objet of type AliMagF via
75 SetField().
76 Example:
77 gAlice->SetField(new AliMagFCM("Map2", "$(ALICE_ROOT)/data/field01.dat",2,1.,10.));
78
79 Revision 1.46  2000/12/14 19:29:27  fca
80 galice.cuts was not read any more
81
82 Revision 1.45  2000/11/30 07:12:49  alibrary
83 Introducing new Rndm and QA classes
84
85 Revision 1.44  2000/10/26 13:58:59  morsch
86 Add possibility to choose the lego generator (of type AliGeneratorLego or derived) when running
87 RunLego(). Default is the base class AliGeneratorLego.
88
89 Revision 1.43  2000/10/09 09:43:17  fca
90 Special remapping of hits for TPC and TRD. End-of-primary action introduced
91
92 Revision 1.42  2000/10/02 21:28:14  fca
93 Removal of useless dependecies via forward declarations
94
95 Revision 1.41  2000/07/13 16:19:09  fca
96 Mainly coding conventions + some small bug fixes
97
98 Revision 1.40  2000/07/12 08:56:25  fca
99 Coding convention correction and warning removal
100
101 Revision 1.39  2000/07/11 18:24:59  fca
102 Coding convention corrections + few minor bug fixes
103
104 Revision 1.38  2000/06/20 13:05:45  fca
105 Writing down the TREE headers before job starts
106
107 Revision 1.37  2000/06/09 20:05:11  morsch
108 Introduce possibility to chose magnetic field version 3: AliMagFDM + field02.dat
109
110 Revision 1.36  2000/06/08 14:03:58  hristov
111 Only one initializer for a default argument
112
113 Revision 1.35  2000/06/07 10:13:14  hristov
114 Delete only existent objects.
115
116 Revision 1.34  2000/05/18 10:45:38  fca
117 Delete Particle Factory properly
118
119 Revision 1.33  2000/05/16 13:10:40  fca
120 New method IsNewTrack and fix for a problem in Father-Daughter relations
121
122 Revision 1.32  2000/04/27 10:38:21  fca
123 Correct termination of Lego Run and introduce Lego getter in AliRun
124
125 Revision 1.31  2000/04/26 10:17:32  fca
126 Changes in Lego for G4 compatibility
127
128 Revision 1.30  2000/04/18 19:11:40  fca
129 Introduce variable Config.C function signature
130
131 Revision 1.29  2000/04/07 11:12:34  fca
132 G4 compatibility changes
133
134 Revision 1.28  2000/04/05 06:51:06  fca
135 Workaround for an HP compiler problem
136
137 Revision 1.27  2000/03/22 18:08:07  fca
138 Rationalisation of the virtual MC interfaces
139
140 Revision 1.26  2000/03/22 13:42:26  fca
141 SetGenerator does not replace an existing generator, ResetGenerator does
142
143 Revision 1.25  2000/02/23 16:25:22  fca
144 AliVMC and AliGeant3 classes introduced
145 ReadEuclid moved from AliRun to AliModule
146
147 Revision 1.24  2000/01/19 17:17:20  fca
148 Introducing a list of lists of hits -- more hits allowed for detector now
149
150 Revision 1.23  1999/12/03 11:14:31  fca
151 Fixing previous wrong checking
152
153 Revision 1.21  1999/11/25 10:40:08  fca
154 Fixing daughters information also in primary tracks
155
156 Revision 1.20  1999/10/04 18:08:49  fca
157 Adding protection against inconsistent Euclid files
158
159 Revision 1.19  1999/09/29 07:50:40  fca
160 Introduction of the Copyright and cvs Log
161
162 */
163
164 ///////////////////////////////////////////////////////////////////////////////
165 //                                                                           //
166 //  Control class for Alice C++                                              //
167 //  Only one single instance of this class exists.                           //
168 //  The object is created in main program aliroot                            //
169 //  and is pointed by the global gAlice.                                     //
170 //                                                                           //
171 //   -Supports the list of all Alice Detectors (fModules).                 //
172 //   -Supports the list of particles (fParticles).                           //
173 //   -Supports the Trees.                                                    //
174 //   -Supports the geometry.                                                 //
175 //   -Supports the event display.                                            //
176 //Begin_Html
177 /*
178 <img src="picts/AliRunClass.gif">
179 */
180 //End_Html
181 //Begin_Html
182 /*
183 <img src="picts/alirun.gif">
184 */
185 //End_Html
186 //                                                                           //
187 ///////////////////////////////////////////////////////////////////////////////
188
189 #include <stdlib.h>
190 #include <stdio.h>
191 #include <string.h>
192 #include <iostream.h>
193  
194 #include <TFile.h>
195 #include <TRandom.h>
196 #include <TBRIK.h> 
197 #include <TNode.h> 
198 #include <TCint.h> 
199 #include <TSystem.h>
200 #include <TObjectTable.h>
201 #include <TTree.h>
202 #include <TGeometry.h>
203 #include <TROOT.h>
204 #include <TBrowser.h>
205 #include <TFolder.h>
206
207 #include "TParticle.h"
208 #include "AliRun.h"
209 #include "AliDisplay.h"
210 #include "AliMC.h"
211 #include "AliLego.h"
212 #include "AliMagFC.h"
213 #include "AliMagFCM.h"
214 #include "AliMagFDM.h"
215 #include "AliHit.h"
216 #include "TRandom3.h"
217 #include "AliMCQA.h"
218 #include "AliGenerator.h"
219 #include "AliLegoGenerator.h"
220 #include "AliConfig.h"
221 #include "AliStack.h"
222 #include "AliGenEventHeader.h"
223 #include "AliHeader.h"
224
225 #include "AliDetector.h"
226
227 AliRun *gAlice;
228
229 ClassImp(AliRun)
230
231 //_____________________________________________________________________________
232 AliRun::AliRun()
233 {
234   //
235   // Default constructor for AliRun
236   //
237   fHeader    = 0;
238   fRun       = 0;
239   fEvent     = 0;
240   fStack     = 0;
241   fModules   = 0;
242   fGenerator = 0;
243   fTreeD     = 0;
244   fTreeH     = 0;
245   fTreeE     = 0;
246   fTreeR     = 0;
247   fTreeS     = 0;
248   fGeometry  = 0;
249   fDisplay   = 0;
250   fField     = 0;
251   fMC        = 0;
252   fNdets     = 0;
253   fImedia    = 0;
254   fTrRmax    = 1.e10;
255   fTrZmax    = 1.e10;
256   fInitDone  = kFALSE;
257   fLego      = 0;
258   fPDGDB     = 0;        //Particle factory object!
259   fHitLists  = 0;
260   fConfigFunction    = "\0";
261   fRandom = 0;
262   fMCQA = 0;
263   fTransParName = "\0";
264   fBaseFileName = ".\0";
265   fDebug        = 0;
266 }
267
268 //_____________________________________________________________________________
269 AliRun::AliRun(const char *name, const char *title)
270   : TNamed(name,title)
271 {
272   //
273   //  Constructor for the main processor.
274   //  Creates the geometry
275   //  Creates the list of Detectors.
276   //  Creates the list of particles.
277   //
278   Int_t i;
279   
280   gAlice     = this;
281   fTreeD     = 0;
282   fTreeH     = 0;
283   fTreeE     = 0;
284   fTreeR     = 0;
285   fTreeS     = 0;
286   fTrRmax    = 1.e10;
287   fTrZmax    = 1.e10;
288   fGenerator = 0;
289   fInitDone  = kFALSE;
290   fLego      = 0;
291   fField     = 0;
292   fConfigFunction    = "Config();";
293
294   // Set random number generator
295   gRandom = fRandom = new TRandom3();
296
297   if (gSystem->Getenv("CONFIG_SEED")) {
298      gRandom->SetSeed((UInt_t)atoi(gSystem->Getenv("CONFIG_SEED")));
299   }
300   
301   gROOT->GetListOfBrowsables()->Add(this,name);
302   //
303   // Particle stack
304   fStack = new AliStack(10000);
305   // create the support list for the various Detectors
306   fModules = new TObjArray(77);
307   //
308   // Create the TNode geometry for the event display
309   
310   BuildSimpleGeometry();
311   
312   fHeader    = new AliHeader();
313   fRun       = 0;
314   fEvent     = 0;
315   //
316   fDisplay = 0;
317   //
318   // Create default mag field
319   SetField();
320   //
321   fMC      = gMC;
322   //
323   // Prepare the tracking medium lists
324   fImedia = new TArrayI(1000);
325   for(i=0;i<1000;i++) (*fImedia)[i]=-99;
326   //
327   // Make particles
328   fPDGDB     = TDatabasePDG::Instance();        //Particle factory object!
329
330   AliConfig::Instance()->Add(fPDGDB); 
331   //
332   // Create HitLists list
333   fHitLists  = new TList();
334   //
335   SetTransPar();
336   fBaseFileName = ".\0";
337   //
338   fDebug        = 0;
339 }
340
341
342 //_____________________________________________________________________________
343 AliRun::~AliRun()
344 {
345   //
346   // Default AliRun destructor
347   //
348   delete fImedia;
349   delete fField;
350   delete fMC;
351   delete fGeometry;
352   delete fDisplay;
353   delete fGenerator;
354   delete fLego;
355   delete fTreeD;
356   delete fTreeH;
357   delete fTreeE;
358   delete fTreeR;
359   delete fTreeS;
360   if (fModules) {
361     fModules->Delete();
362     delete fModules;
363   }
364   delete fStack;
365   delete fHitLists;
366   delete fPDGDB;
367   delete fMCQA;
368   delete fHeader;
369 }
370
371 //_____________________________________________________________________________
372 void AliRun::AddHit(Int_t id, Int_t track, Int_t *vol, Float_t *hits) const
373 {
374   //
375   //  Add a hit to detector id
376   //
377   TObjArray &dets = *fModules;
378   if(dets[id]) ((AliModule*) dets[id])->AddHit(track,vol,hits);
379 }
380
381 //_____________________________________________________________________________
382 void AliRun::AddDigit(Int_t id, Int_t *tracks, Int_t *digits) const
383 {
384   //
385   // Add digit to detector id
386   //
387   TObjArray &dets = *fModules;
388   if(dets[id]) ((AliModule*) dets[id])->AddDigit(tracks,digits);
389 }
390
391 //_____________________________________________________________________________
392 void AliRun::Browse(TBrowser *b)
393 {
394   //
395   // Called when the item "Run" is clicked on the left pane
396   // of the Root browser.
397   // It displays the Root Trees and all detectors.
398   //
399   if(!fStack) fStack=fHeader->Stack();
400   TTree*  pTreeK = fStack->TreeK();
401     
402   if (pTreeK) b->Add(pTreeK,pTreeK->GetName());
403   if (fTreeH) b->Add(fTreeH,fTreeH->GetName());
404   if (fTreeD) b->Add(fTreeD,fTreeD->GetName());
405   if (fTreeE) b->Add(fTreeE,fTreeE->GetName());
406   if (fTreeR) b->Add(fTreeR,fTreeR->GetName());
407   if (fTreeS) b->Add(fTreeS,fTreeS->GetName());
408   
409   TIter next(fModules);
410   AliModule *detector;
411   while((detector = (AliModule*)next())) {
412     b->Add(detector,detector->GetName());
413   }
414   b->Add(fMCQA,"AliMCQA");
415 }
416
417 //_____________________________________________________________________________
418 void AliRun::Build()
419 {
420   //
421   // Initialize Alice geometry
422   // Dummy routine
423   //
424 }
425  
426 //_____________________________________________________________________________
427 void AliRun::BuildSimpleGeometry()
428 {
429   //
430   // Create a simple TNode geometry used by Root display engine
431   //
432   // Initialise geometry
433   //
434   fGeometry = new TGeometry("AliceGeom","Galice Geometry for Hits");
435   new TMaterial("void","Vacuum",0,0,0);  //Everything is void
436   TBRIK *brik = new TBRIK("S_alice","alice volume","void",2000,2000,3000);
437   brik->SetVisibility(0);
438   new TNode("alice","alice","S_alice");
439 }
440
441 //_____________________________________________________________________________
442 void AliRun::CleanDetectors()
443 {
444   //
445   // Clean Detectors at the end of event
446   //
447   TIter next(fModules);
448   AliModule *detector;
449   while((detector = (AliModule*)next())) {
450     detector->FinishEvent();
451   }
452 }
453
454 //_____________________________________________________________________________
455 Int_t AliRun::DistancetoPrimitive(Int_t, Int_t)
456 {
457   //
458   // Return the distance from the mouse to the AliRun object
459   // Dummy routine
460   //
461   return 9999;
462 }
463
464 //_____________________________________________________________________________
465 void AliRun::DumpPart (Int_t i) const
466 {
467   //
468   // Dumps particle i in the stack
469   //
470     fStack->DumpPart(i);
471 }
472
473 //_____________________________________________________________________________
474 void AliRun::DumpPStack () const
475 {
476   //
477   // Dumps the particle stack
478   //
479     fStack->DumpPStack();
480 }
481
482 //_____________________________________________________________________________
483 void  AliRun::SetField(AliMagF* magField)
484 {
485     // Set Magnetic Field Map
486     fField = magField;
487     fField->ReadField();
488 }
489
490 //_____________________________________________________________________________
491 void AliRun::SetField(Int_t type, Int_t version, Float_t scale,
492                       Float_t maxField, char* filename)
493 {
494   //
495   //  Set magnetic field parameters
496   //  type      Magnetic field transport flag 0=no field, 2=helix, 3=Runge Kutta
497   //  version   Magnetic field map version (only 1 active now)
498   //  scale     Scale factor for the magnetic field
499   //  maxField  Maximum value for the magnetic field
500
501   //
502   // --- Sanity check on mag field flags
503   if(fField) delete fField;
504   if(version==1) {
505     fField = new AliMagFC("Map1"," ",type,scale,maxField);
506   } else if(version<=2) {
507     fField = new AliMagFCM("Map2-3",filename,type,scale,maxField);
508     fField->ReadField();
509   } else if(version==3) {
510     fField = new AliMagFDM("Map4",filename,type,scale,maxField);
511     fField->ReadField();
512   } else {
513     Warning("SetField","Invalid map %d\n",version);
514   }
515 }
516  
517 //_____________________________________________________________________________
518 void AliRun::PreTrack()
519 {
520      TObjArray &dets = *fModules;
521      AliModule *module;
522
523      for(Int_t i=0; i<=fNdets; i++)
524        if((module = (AliModule*)dets[i]))
525          module->PreTrack();
526
527      fMCQA->PreTrack();
528 }
529
530 //_____________________________________________________________________________
531 void AliRun::PostTrack()
532 {
533      TObjArray &dets = *fModules;
534      AliModule *module;
535
536      for(Int_t i=0; i<=fNdets; i++)
537        if((module = (AliModule*)dets[i]))
538          module->PostTrack();
539 }
540
541 //_____________________________________________________________________________
542 void AliRun::FinishPrimary()
543 {
544   //
545   // Called  at the end of each primary track
546   //
547   
548   //  static Int_t count=0;
549   //  const Int_t times=10;
550   // This primary is finished, purify stack
551   fStack->PurifyKine();
552
553   TIter next(fModules);
554   AliModule *detector;
555   while((detector = (AliModule*)next())) {
556     detector->FinishPrimary();
557   }
558
559   // Write out hits if any
560   if (gAlice->TreeH()) {
561     gAlice->TreeH()->Fill();
562   }
563   
564   //
565   //  if(++count%times==1) gObjectTable->Print();
566 }
567
568 //_____________________________________________________________________________
569 void AliRun::BeginPrimary()
570 {
571   //
572   // Called  at the beginning of each primary track
573   //
574   
575   // Reset Hits info
576   gAlice->ResetHits();
577
578 }
579
580 //_____________________________________________________________________________
581 void AliRun::FinishEvent()
582 {
583   //
584   // Called at the end of the event.
585   //
586   
587   //
588   if(fLego) fLego->FinishEvent();
589
590   //Update the energy deposit tables
591   Int_t i;
592   for(i=0;i<fEventEnergy.GetSize();i++) {
593     fSummEnergy[i]+=fEventEnergy[i];
594     fSum2Energy[i]+=fEventEnergy[i]*fEventEnergy[i];
595   }
596
597
598   
599   // Update Header information 
600
601   fHeader->SetNprimary(fStack->GetNprimary());
602   fHeader->SetNtrack(fStack->GetNtrack());  
603
604   
605   // Write out the kinematics
606   fStack->FinishEvent();
607    
608   // Write out the event Header information
609   if (fTreeE) {
610       fHeader->SetStack(fStack);
611       fTreeE->Fill();
612   }
613   
614   
615   // Write Tree headers
616   TTree* pTreeK = fStack->TreeK();
617   if (pTreeK) pTreeK->Write(0,TObject::kOverwrite);
618   if (fTreeH) fTreeH->Write(0,TObject::kOverwrite);
619   
620   ++fEvent;
621 }
622
623 //_____________________________________________________________________________
624 void AliRun::FinishRun()
625 {
626   //
627   // Called at the end of the run.
628   //
629
630   //
631   if(fLego) fLego->FinishRun();
632   
633   // Clean detector information
634   TIter next(fModules);
635   AliModule *detector;
636   while((detector = (AliModule*)next())) {
637     detector->FinishRun();
638   }
639   
640   //Output energy summary tables
641   EnergySummary();
642
643   TFile *file = fTreeE->GetCurrentFile();
644
645   file->cd();
646   
647   fTreeE->Write(0,TObject::kOverwrite);
648   
649   // Write AliRun info and all detectors parameters
650   Write(0,TObject::kOverwrite);
651
652   // Clean tree information
653
654   fStack->FinishRun();
655   
656   if (fTreeH) {
657     delete fTreeH; fTreeH = 0;
658   }
659   if (fTreeD) {
660     delete fTreeD; fTreeD = 0;
661   }
662   if (fTreeR) {
663     delete fTreeR; fTreeR = 0;
664   }
665   if (fTreeE) {
666     delete fTreeE; fTreeE = 0;
667   }
668   if (fTreeS) {
669     delete fTreeS; fTreeS = 0;
670   }
671     
672   // Close output file
673   file->Write();
674 }
675
676 //_____________________________________________________________________________
677 void AliRun::FlagTrack(Int_t track)
678 {
679   // Delegate to stack
680   //
681     fStack->FlagTrack(track);
682 }
683  
684 //_____________________________________________________________________________
685 void AliRun::EnergySummary()
686 {
687   //
688   // Print summary of deposited energy
689   //
690
691   Int_t ndep=0;
692   Float_t edtot=0;
693   Float_t ed, ed2;
694   Int_t kn, i, left, j, id;
695   const Float_t kzero=0;
696   Int_t ievent=fHeader->GetEvent()+1;
697   //
698   // Energy loss information
699   if(ievent) {
700     printf("***************** Energy Loss Information per event (GEV) *****************\n");
701     for(kn=1;kn<fEventEnergy.GetSize();kn++) {
702       ed=fSummEnergy[kn];
703       if(ed>0) {
704         fEventEnergy[ndep]=kn;
705         if(ievent>1) {
706           ed=ed/ievent;
707           ed2=fSum2Energy[kn];
708           ed2=ed2/ievent;
709           ed2=100*TMath::Sqrt(TMath::Max(ed2-ed*ed,kzero))/ed;
710         } else 
711           ed2=99;
712         fSummEnergy[ndep]=ed;
713         fSum2Energy[ndep]=TMath::Min((Float_t) 99.,TMath::Max(ed2,kzero));
714         edtot+=ed;
715         ndep++;
716       }
717     }
718     for(kn=0;kn<(ndep-1)/3+1;kn++) {
719       left=ndep-kn*3;
720       for(i=0;i<(3<left?3:left);i++) {
721         j=kn*3+i;
722         id=Int_t (fEventEnergy[j]+0.1);
723         printf(" %s %10.3f +- %10.3f%%;",gMC->VolName(id),fSummEnergy[j],fSum2Energy[j]);
724       }
725       printf("\n");
726     }
727     //
728     // Relative energy loss in different detectors
729     printf("******************** Relative Energy Loss per event ********************\n");
730     printf("Total energy loss per event %10.3f GeV\n",edtot);
731     for(kn=0;kn<(ndep-1)/5+1;kn++) {
732       left=ndep-kn*5;
733       for(i=0;i<(5<left?5:left);i++) {
734         j=kn*5+i;
735         id=Int_t (fEventEnergy[j]+0.1);
736         printf(" %s %10.3f%%;",gMC->VolName(id),100*fSummEnergy[j]/edtot);
737       }
738       printf("\n");
739     }
740     for(kn=0;kn<75;kn++) printf("*"); 
741     printf("\n");
742   }
743   //
744   // Reset the TArray's
745   //  fEventEnergy.Set(0);
746   //  fSummEnergy.Set(0);
747   //  fSum2Energy.Set(0);
748 }
749
750 //_____________________________________________________________________________
751 AliModule *AliRun::GetModule(const char *name) const
752 {
753   //
754   // Return pointer to detector from name
755   //
756   return (AliModule*)fModules->FindObject(name);
757 }
758  
759 //_____________________________________________________________________________
760 AliDetector *AliRun::GetDetector(const char *name) const
761 {
762   //
763   // Return pointer to detector from name
764   //
765   return (AliDetector*)fModules->FindObject(name);
766 }
767  
768 //_____________________________________________________________________________
769 Int_t AliRun::GetModuleID(const char *name) const
770 {
771   //
772   // Return galice internal detector identifier from name
773   //
774   Int_t i=-1;
775   TObject *mod=fModules->FindObject(name);
776   if(mod) i=fModules->IndexOf(mod);
777   return i;
778 }
779  
780 //_____________________________________________________________________________
781 Int_t AliRun::GetEvent(Int_t event)
782 {
783   //
784   // Connect the Trees Kinematics and Hits for event # event
785   // Set branch addresses
786   //
787
788   // Reset existing structures
789   ResetHits();
790   ResetDigits();
791   ResetSDigits();
792   
793   // Delete Trees already connected
794   if (fTreeH) { delete fTreeH; fTreeH = 0;}
795   if (fTreeD) { delete fTreeD; fTreeD = 0;}
796   if (fTreeR) { delete fTreeR; fTreeR = 0;}
797   if (fTreeS) { delete fTreeS; fTreeS = 0;}
798
799  // Create the particle stack
800   if (fHeader) delete fHeader; 
801   fHeader = 0;
802   
803   // Get header from file
804   if(fTreeE) {
805       fTreeE->SetBranchAddress("Header", &fHeader);
806
807       if (!fTreeE->GetEntry(event)) {
808         Error("GetEvent","Cannot find event:%d\n",event);
809         return -1;
810       }
811   }  
812   else {
813       Error("GetEvent","Cannot find Header Tree (TE)\n");
814       return -1;
815   }
816
817   // Get the stack from the header, set fStack to 0 if it 
818   // fails to get event
819   if (fStack) delete fStack;
820   fStack = fHeader->Stack();
821   if (fStack) {
822     if (!fStack->GetEvent(event,0)) fStack = 0;
823   }
824
825   //
826   TFile *file = fTreeE->GetCurrentFile();
827   char treeName[20];
828   file->cd();
829
830   // Get Hits Tree header from file
831   sprintf(treeName,"TreeH%d",event);
832   fTreeH = (TTree*)gDirectory->Get(treeName);
833   if (!fTreeH) {
834     Error("GetEvent","cannot find Hits Tree for event:%d\n",event);
835   }
836   
837   // Get Digits Tree header from file
838   sprintf(treeName,"TreeD%d",event);
839   fTreeD = (TTree*)gDirectory->Get(treeName);
840   if (!fTreeD) {
841     // Warning("GetEvent","cannot find Digits Tree for event:%d\n",event);
842   }
843
844   file->cd();
845
846   // Get SDigits Tree header from file
847   sprintf(treeName,"TreeS%d",event);
848   fTreeS = (TTree*)gDirectory->Get(treeName);
849   if (!fTreeS) {
850     // Warning("GetEvent","cannot find SDigits Tree for event:%d\n",event);
851   }
852
853   file->cd();
854   
855   // Get Reconstruct Tree header from file
856   sprintf(treeName,"TreeR%d",event);
857   fTreeR = (TTree*)gDirectory->Get(treeName);
858   if (!fTreeR) {
859     //    printf("WARNING: cannot find Reconstructed Tree for event:%d\n",event);
860   }
861
862   file->cd();
863  
864   // Set Trees branch addresses
865   TIter next(fModules);
866   AliModule *detector;
867   while((detector = (AliModule*)next())) {
868     detector->SetTreeAddress();
869   }
870
871   return fStack->GetNtrack();
872 }
873
874 //_____________________________________________________________________________
875 TGeometry *AliRun::GetGeometry()
876 {
877   //
878   // Import Alice geometry from current file
879   // Return pointer to geometry object
880   //
881   if (!fGeometry) fGeometry = (TGeometry*)gDirectory->Get("AliceGeom");
882   //
883   // Unlink and relink nodes in detectors
884   // This is bad and there must be a better way...
885   //
886   
887   TIter next(fModules);
888   AliModule *detector;
889   while((detector = (AliModule*)next())) {
890     TList *dnodes=detector->Nodes();
891     Int_t j;
892     TNode *node, *node1;
893     for ( j=0; j<dnodes->GetSize(); j++) {
894       node = (TNode*) dnodes->At(j);
895       node1 = fGeometry->GetNode(node->GetName());
896       dnodes->Remove(node);
897       dnodes->AddAt(node1,j);
898     }
899   }
900   return fGeometry;
901 }
902
903 //_____________________________________________________________________________
904 void AliRun::GetNextTrack(Int_t &mtrack, Int_t &ipart, Float_t *pmom,
905                           Float_t &e, Float_t *vpos, Float_t *polar,
906                           Float_t &tof)
907 {
908   // Delegate to stack
909   //
910     fStack->GetNextTrack(mtrack, ipart, pmom, e, vpos, polar, tof);  
911 }
912
913 //_____________________________________________________________________________
914 Int_t AliRun::GetPrimary(Int_t track) const
915 {
916   //
917   // return number of primary that has generated track
918   //
919     return fStack->GetPrimary(track);
920 }
921  
922 //_____________________________________________________________________________
923 void AliRun::InitMC(const char *setup)
924 {
925   //
926   // Initialize the Alice setup
927   //
928
929   if(fInitDone) {
930     Warning("Init","Cannot initialise AliRun twice!\n");
931     return;
932   }
933     
934   gROOT->LoadMacro(setup);
935   gInterpreter->ProcessLine(fConfigFunction.Data());
936
937
938   gMC->DefineParticles();  //Create standard MC particles
939
940   TObject *objfirst, *objlast;
941
942   fNdets = fModules->GetLast()+1;
943
944   //
945   //=================Create Materials and geometry
946   gMC->Init();
947
948   // Added also after in case of interactive initialisation of modules
949   fNdets = fModules->GetLast()+1;
950
951    TIter next(fModules);
952    AliModule *detector;
953    while((detector = (AliModule*)next())) {
954       detector->SetTreeAddress();
955       objlast = gDirectory->GetList()->Last();
956       
957       // Add Detector histograms in Detector list of histograms
958       if (objlast) objfirst = gDirectory->GetList()->After(objlast);
959       else         objfirst = gDirectory->GetList()->First();
960       while (objfirst) {
961         detector->Histograms()->Add(objfirst);
962         objfirst = gDirectory->GetList()->After(objfirst);
963       }
964    }
965    ReadTransPar(); //Read the cuts for all materials
966    
967    MediaTable(); //Build the special IMEDIA table
968    
969    //Initialise geometry deposition table
970    fEventEnergy.Set(gMC->NofVolumes()+1);
971    fSummEnergy.Set(gMC->NofVolumes()+1);
972    fSum2Energy.Set(gMC->NofVolumes()+1);
973    
974    //Compute cross-sections
975    gMC->BuildPhysics();
976    
977    //Write Geometry object to current file.
978    fGeometry->Write();
979    
980    fInitDone = kTRUE;
981
982    fMCQA = new AliMCQA(fNdets);
983
984    AliConfig *config = AliConfig::Instance();
985    //
986    // Save stuff at the beginning of the file to avoid file corruption
987    Write();
988 }
989
990 //_____________________________________________________________________________
991 void AliRun::MediaTable()
992 {
993   //
994   // Built media table to get from the media number to
995   // the detector id
996   //
997   Int_t kz, nz, idt, lz, i, k, ind;
998   //  Int_t ibeg;
999   TObjArray &dets = *gAlice->Detectors();
1000   AliModule *det;
1001   //
1002   // For all detectors
1003   for (kz=0;kz<fNdets;kz++) {
1004     // If detector is defined
1005     if((det=(AliModule*) dets[kz])) {
1006         TArrayI &idtmed = *(det->GetIdtmed()); 
1007         for(nz=0;nz<100;nz++) {
1008         // Find max and min material number
1009         if((idt=idtmed[nz])) {
1010           det->LoMedium() = det->LoMedium() < idt ? det->LoMedium() : idt;
1011           det->HiMedium() = det->HiMedium() > idt ? det->HiMedium() : idt;
1012         }
1013       }
1014       if(det->LoMedium() > det->HiMedium()) {
1015         det->LoMedium() = 0;
1016         det->HiMedium() = 0;
1017       } else {
1018         if(det->HiMedium() > fImedia->GetSize()) {
1019           Error("MediaTable","Increase fImedia from %d to %d",
1020                 fImedia->GetSize(),det->HiMedium());
1021           return;
1022         }
1023         // Tag all materials in rage as belonging to detector kz
1024         for(lz=det->LoMedium(); lz<= det->HiMedium(); lz++) {
1025           (*fImedia)[lz]=kz;
1026         }
1027       }
1028     }
1029   }
1030   //
1031   // Print summary table
1032   printf(" Traking media ranges:\n");
1033   for(i=0;i<(fNdets-1)/6+1;i++) {
1034     for(k=0;k< (6<fNdets-i*6?6:fNdets-i*6);k++) {
1035       ind=i*6+k;
1036       det=(AliModule*)dets[ind];
1037       if(det)
1038         printf(" %6s: %3d -> %3d;",det->GetName(),det->LoMedium(),
1039                det->HiMedium());
1040       else
1041         printf(" %6s: %3d -> %3d;","NULL",0,0);
1042     }
1043     printf("\n");
1044   }
1045 }
1046
1047 //____________________________________________________________________________
1048 void AliRun::SetGenerator(AliGenerator *generator)
1049 {
1050   //
1051   // Load the event generator
1052   //
1053   if(!fGenerator) fGenerator = generator;
1054 }
1055
1056 //____________________________________________________________________________
1057 void AliRun::ResetGenerator(AliGenerator *generator)
1058 {
1059   //
1060   // Load the event generator
1061   //
1062   if(fGenerator)
1063     if(generator)
1064       Warning("ResetGenerator","Replacing generator %s with %s\n",
1065               fGenerator->GetName(),generator->GetName());
1066     else
1067       Warning("ResetGenerator","Replacing generator %s with NULL\n",
1068               fGenerator->GetName());
1069   fGenerator = generator;
1070 }
1071
1072 //____________________________________________________________________________
1073 void AliRun::SetTransPar(char *filename)
1074 {
1075   fTransParName = filename;
1076 }
1077
1078 //____________________________________________________________________________
1079 void AliRun::SetBaseFile(char *filename)
1080 {
1081   fBaseFileName = filename;
1082 }
1083
1084 //____________________________________________________________________________
1085 void AliRun::ReadTransPar()
1086 {
1087   //
1088   // Read filename to set the transport parameters
1089   //
1090
1091
1092   const Int_t kncuts=10;
1093   const Int_t knflags=11;
1094   const Int_t knpars=kncuts+knflags;
1095   const char kpars[knpars][7] = {"CUTGAM" ,"CUTELE","CUTNEU","CUTHAD","CUTMUO",
1096                                "BCUTE","BCUTM","DCUTE","DCUTM","PPCUTM","ANNI",
1097                                "BREM","COMP","DCAY","DRAY","HADR","LOSS",
1098                                "MULS","PAIR","PHOT","RAYL"};
1099   char line[256];
1100   char detName[7];
1101   char* filtmp;
1102   Float_t cut[kncuts];
1103   Int_t flag[knflags];
1104   Int_t i, itmed, iret, ktmed, kz;
1105   FILE *lun;
1106   //
1107   // See whether the file is there
1108   filtmp=gSystem->ExpandPathName(fTransParName.Data());
1109   lun=fopen(filtmp,"r");
1110   delete [] filtmp;
1111   if(!lun) {
1112     Warning("ReadTransPar","File %s does not exist!\n",fTransParName.Data());
1113     return;
1114   }
1115   //
1116   if(fDebug) {
1117     printf(" "); for(i=0;i<60;i++) printf("*"); printf("\n");
1118     printf(" *%59s\n","*");
1119     printf(" *       Please check carefully what you are doing!%10s\n","*");
1120     printf(" *%59s\n","*");
1121   }
1122   //
1123   while(1) {
1124     // Initialise cuts and flags
1125     for(i=0;i<kncuts;i++) cut[i]=-99;
1126     for(i=0;i<knflags;i++) flag[i]=-99;
1127     itmed=0;
1128     for(i=0;i<256;i++) line[i]='\0';
1129     // Read up to the end of line excluded
1130     iret=fscanf(lun,"%[^\n]",line);
1131     if(iret<0) {
1132       //End of file
1133       fclose(lun);
1134       if(fDebug){
1135         printf(" *%59s\n","*");
1136         printf(" "); for(i=0;i<60;i++) printf("*"); printf("\n");
1137       }
1138       return;
1139     }
1140     // Read the end of line
1141     fscanf(lun,"%*c");
1142     if(!iret) continue;
1143     if(line[0]=='*') continue;
1144     // Read the numbers
1145     iret=sscanf(line,"%s %d %f %f %f %f %f %f %f %f %f %f %d %d %d %d %d %d %d %d %d %d %d",
1146                 detName,&itmed,&cut[0],&cut[1],&cut[2],&cut[3],&cut[4],&cut[5],&cut[6],&cut[7],&cut[8],
1147                 &cut[9],&flag[0],&flag[1],&flag[2],&flag[3],&flag[4],&flag[5],&flag[6],&flag[7],
1148                 &flag[8],&flag[9],&flag[10]);
1149     if(!iret) continue;
1150     if(iret<0) {
1151       //reading error
1152       Warning("ReadTransPar","Error reading file %s\n",fTransParName.Data());
1153       continue;
1154     }
1155     // Check that the module exist
1156     AliModule *mod = GetModule(detName);
1157     if(mod) {
1158       // Get the array of media numbers
1159       TArrayI &idtmed = *mod->GetIdtmed();
1160       // Check that the tracking medium code is valid
1161       if(0<=itmed && itmed < 100) {
1162         ktmed=idtmed[itmed];
1163         if(!ktmed) {
1164           Warning("ReadTransPar","Invalid tracking medium code %d for %s\n",itmed,mod->GetName());
1165           continue;
1166         }
1167         // Set energy thresholds
1168         for(kz=0;kz<kncuts;kz++) {
1169           if(cut[kz]>=0) {
1170             if(fDebug) printf(" *  %-6s set to %10.3E for tracking medium code %4d for %s\n",
1171                    kpars[kz],cut[kz],itmed,mod->GetName());
1172             gMC->Gstpar(ktmed,kpars[kz],cut[kz]);
1173           }
1174         }
1175         // Set transport mechanisms
1176         for(kz=0;kz<knflags;kz++) {
1177           if(flag[kz]>=0) {
1178             if(fDebug) printf(" *  %-6s set to %10d for tracking medium code %4d for %s\n",
1179                    kpars[kncuts+kz],flag[kz],itmed,mod->GetName());
1180             gMC->Gstpar(ktmed,kpars[kncuts+kz],Float_t(flag[kz]));
1181           }
1182         }
1183       } else {
1184         Warning("ReadTransPar","Invalid medium code %d *\n",itmed);
1185         continue;
1186       }
1187     } else {
1188       if(fDebug) printf("%s::ReadTransParModule: %s not present\n",ClassName(),detName);
1189       continue;
1190     }
1191   }
1192 }
1193
1194
1195 //_____________________________________________________________________________
1196 void AliRun::MakeTree(Option_t *option, const char *file)
1197 {
1198   //
1199   //  Create the ROOT trees
1200   //  Loop on all detectors to create the Root branch (if any)
1201   //
1202
1203   char hname[30];
1204   //
1205   // Analyse options
1206   const char *oK = strstr(option,"K");
1207   const char *oH = strstr(option,"H");
1208   const char *oE = strstr(option,"E");
1209   const char *oD = strstr(option,"D");
1210   const char *oR = strstr(option,"R");
1211   const char *oS = strstr(option,"S");
1212   //
1213
1214   TDirectory *cwd = gDirectory;
1215
1216   TBranch *branch = 0;
1217   
1218   if (oK) fStack->MakeTree(fEvent, file);
1219
1220   if (oE && !fTreeE) {
1221     fTreeE = new TTree("TE","Header");
1222     branch = fTreeE->Branch("Header", "AliHeader", &fHeader, 4000, 0);         
1223     branch->SetAutoDelete(kFALSE);           
1224     TFolder *folder = (TFolder *)gROOT->FindObjectAny("/Folders/RunMC/Event/Header");
1225     if (folder) folder->Add(fHeader);
1226 //    branch = fTreeE->Branch("Stack","AliStack", &fStack, 4000, 0);
1227 //    branch->SetAutoDelete(kFALSE);         
1228 //    if (folder) folder->Add(fStack);
1229     fTreeE->Write(0,TObject::kOverwrite);
1230   }
1231   
1232   if (file && branch) {
1233     char * outFile = new char[strlen(gAlice->GetBaseFile())+strlen(file)+2];
1234     sprintf(outFile,"%s/%s",GetBaseFile(),file);
1235     branch->SetFile(outFile);
1236     TIter next( branch->GetListOfBranches());
1237     while ((branch=(TBranch*)next())) {
1238        branch->SetFile(outFile);
1239     } 
1240     if (GetDebug()>1)
1241         printf("* MakeBranch * Diverting Branch %s to file %s\n", branch->GetName(),file);
1242     cwd->cd();
1243     delete outFile;
1244   }
1245   
1246   if (oH && !fTreeH) {
1247     sprintf(hname,"TreeH%d",fEvent);
1248     fTreeH = new TTree(hname,"Hits");
1249     fTreeH->SetAutoSave(1000000000); //no autosave
1250     fTreeH->Write(0,TObject::kOverwrite);
1251   }
1252   if (oD && !fTreeD) {
1253     sprintf(hname,"TreeD%d",fEvent);
1254     fTreeD = new TTree(hname,"Digits");
1255     fTreeD->Write(0,TObject::kOverwrite);
1256   }
1257   if (oS && !fTreeS) {
1258     sprintf(hname,"TreeS%d",fEvent);
1259     fTreeS = new TTree(hname,"SDigits");
1260     fTreeS->Write(0,TObject::kOverwrite);
1261   }
1262   if (oR && !fTreeR) {
1263     sprintf(hname,"TreeR%d",fEvent);
1264     fTreeR = new TTree(hname,"Reconstruction");
1265     fTreeR->Write(0,TObject::kOverwrite);
1266   }
1267
1268   //
1269   // Create a branch for hits/digits for each detector
1270   // Each branch is a TClonesArray. Each data member of the Hits classes
1271   // will be in turn a subbranch of the detector master branch
1272   TIter next(fModules);
1273   AliModule *detector;
1274   while((detector = (AliModule*)next())) {
1275      if (oH) detector->MakeBranch(option,file);
1276   }
1277 }
1278
1279 //_____________________________________________________________________________
1280 TParticle* AliRun::Particle(Int_t i)
1281 {
1282     return fStack->Particle(i);
1283 }
1284
1285 //_____________________________________________________________________________
1286 void AliRun::BeginEvent()
1287 {
1288     // Clean-up previous event
1289     // Energy scores  
1290     fEventEnergy.Reset();  
1291     // Clean detector information
1292     CleanDetectors();
1293     // Reset stack info
1294     fStack->Reset();
1295
1296  
1297   //
1298   //  Reset all Detectors & kinematics & trees
1299   //
1300   char hname[30];
1301   //
1302   // Initialise event header
1303   fHeader->Reset(fRun,fEvent);
1304   //
1305   fStack->BeginEvent(fEvent);
1306
1307   //
1308   if(fLego) {
1309     fLego->BeginEvent();
1310     return;
1311   }
1312
1313   //
1314
1315   ResetHits();
1316   ResetDigits();
1317   ResetSDigits();
1318
1319
1320   if(fTreeH) {
1321     fTreeH->Reset();
1322     sprintf(hname,"TreeH%d",fEvent);
1323     fTreeH->SetName(hname);
1324   }
1325   if(fTreeD) {
1326     fTreeD->Reset();
1327     sprintf(hname,"TreeD%d",fEvent);
1328     fTreeD->SetName(hname);
1329     fTreeD->Write(0,TObject::kOverwrite);
1330   }
1331   if(fTreeS) {
1332     fTreeS->Reset();
1333     sprintf(hname,"TreeS%d",fEvent);
1334     fTreeS->SetName(hname);
1335     fTreeS->Write(0,TObject::kOverwrite);
1336   }
1337   if(fTreeR) {
1338     fTreeR->Reset();
1339     sprintf(hname,"TreeR%d",fEvent);
1340     fTreeR->SetName(hname);
1341     fTreeR->Write(0,TObject::kOverwrite);
1342   }
1343 }
1344 //_____________________________________________________________________________
1345 void AliRun::ResetDigits()
1346 {
1347   //
1348   //  Reset all Detectors digits
1349   //
1350   TIter next(fModules);
1351   AliModule *detector;
1352   while((detector = (AliModule*)next())) {
1353      detector->ResetDigits();
1354   }
1355 }
1356
1357 //_____________________________________________________________________________
1358 void AliRun::ResetSDigits()
1359 {
1360   //
1361   //  Reset all Detectors digits
1362   //
1363   TIter next(fModules);
1364   AliModule *detector;
1365   while((detector = (AliModule*)next())) {
1366      detector->ResetSDigits();
1367   }
1368 }
1369
1370 //_____________________________________________________________________________
1371 void AliRun::ResetHits()
1372 {
1373   //
1374   //  Reset all Detectors hits
1375   //
1376   TIter next(fModules);
1377   AliModule *detector;
1378   while((detector = (AliModule*)next())) {
1379      detector->ResetHits();
1380   }
1381 }
1382
1383 //_____________________________________________________________________________
1384 void AliRun::ResetPoints()
1385 {
1386   //
1387   // Reset all Detectors points
1388   //
1389   TIter next(fModules);
1390   AliModule *detector;
1391   while((detector = (AliModule*)next())) {
1392      detector->ResetPoints();
1393   }
1394 }
1395
1396 //_____________________________________________________________________________
1397 void AliRun::RunMC(Int_t nevent, const char *setup)
1398 {
1399   //
1400   // Main function to be called to process a galice run
1401   // example
1402   //    Root > gAlice.Run(); 
1403   // a positive number of events will cause the finish routine
1404   // to be called
1405   //
1406
1407   // check if initialisation has been done
1408   if (!fInitDone) InitMC(setup);
1409   
1410   // Create the Root Tree with one branch per detector
1411
1412    MakeTree("ESDR");
1413
1414   if (gSystem->Getenv("CONFIG_SPLIT_FILE")) {
1415      MakeTree("K","Kine.root");
1416      MakeTree("H","Hits.root");
1417   } else {
1418      MakeTree("KH");
1419   }
1420
1421   gMC->ProcessRun(nevent);
1422
1423   // End of this run, close files
1424   if(nevent>0) FinishRun();
1425 }
1426
1427 //_____________________________________________________________________________
1428 void AliRun::RunReco(const char *selected)
1429 {
1430   //
1431   // Main function to be called to reconstruct Alice event
1432   //  
1433    for (Int_t nevent=0; nevent<gAlice->TreeE()->GetEntries(); nevent++) {
1434      GetEvent(nevent);
1435      // MakeTree("R");
1436      Digits2Reco(selected);
1437    }
1438 }
1439
1440 //_____________________________________________________________________________
1441
1442 void AliRun::Hits2Digits(const char *selected)
1443 {
1444
1445    // Convert Hits to sumable digits
1446    // 
1447    for (Int_t nevent=0; nevent<gAlice->TreeE()->GetEntries(); nevent++) {
1448      GetEvent(nevent);
1449     // MakeTree("D");
1450      Hits2SDigits(selected);
1451      SDigits2Digits(selected);
1452    }  
1453 }
1454
1455
1456 //_____________________________________________________________________________
1457
1458 void AliRun::Tree2Tree(Option_t *option, const char *selected)
1459 {
1460   //
1461   // Function to transform the content of
1462   //  
1463   // - TreeH to TreeS (option "S")
1464   // - TreeS to TreeD (option "D")
1465   // - TreeD to TreeR (option "R")
1466   // 
1467   // If multiple options are specified ("SDR"), transformation will be done in sequence for
1468   // selected detector and for all detectors if none is selected (detector string 
1469   // can contain blank separated list of detector names). 
1470
1471
1472    const char *oS = strstr(option,"S");
1473    const char *oD = strstr(option,"D");
1474    const char *oR = strstr(option,"R");
1475    
1476    TObjArray *detectors = Detectors();
1477
1478    TIter next(detectors);
1479
1480    AliDetector *detector = 0;
1481
1482    TDirectory *cwd = gDirectory;
1483
1484    char outFile[32];
1485    
1486    while((detector = (AliDetector*)next())) {
1487      if (selected) 
1488        if (strcmp(detector->GetName(),selected)) continue;
1489      if (detector->IsActive()){ 
1490        if (gSystem->Getenv("CONFIG_SPLIT_FILE")) {          
1491           if (oS) {
1492             sprintf(outFile,"SDigits.%s.root",detector->GetName());
1493             detector->MakeBranch("S",outFile);
1494           }    
1495           if (oD) {
1496             sprintf(outFile,"Digits.%s.root",detector->GetName());
1497             detector->MakeBranch("D",outFile);
1498           }    
1499           if (oR) {
1500             sprintf(outFile,"Reco.%s.root",detector->GetName());
1501             detector->MakeBranch("R",outFile);
1502           }    
1503        } else {
1504           detector->MakeBranch(option);
1505        }
1506        
1507        cwd->cd(); 
1508
1509        if (oS) {
1510           cout << "Hits2SDigits: Processing " << detector->GetName() << "..." << endl;
1511           detector->Hits2SDigits(); 
1512        }  
1513        if (oD) {
1514           cout << "SDigits2Digits: Processing " << detector->GetName() << "..." << endl;
1515           detector->SDigits2Digits();
1516        } 
1517        if (oR) {
1518           cout << "Digits2Reco: Processing " << detector->GetName() << "..." << endl;
1519           detector->Digits2Reco(); 
1520        }
1521        
1522        cwd->cd();        
1523      }   
1524    }
1525 }
1526
1527
1528 //_____________________________________________________________________________
1529 void AliRun::RunLego(const char *setup, Int_t nc1, Float_t c1min,
1530                      Float_t c1max,Int_t nc2,Float_t c2min,Float_t c2max,
1531                      Float_t rmin,Float_t rmax,Float_t zmax, AliLegoGenerator* gener)
1532 {
1533   //
1534   // Generates lego plots of:
1535   //    - radiation length map phi vs theta
1536   //    - radiation length map phi vs eta
1537   //    - interaction length map
1538   //    - g/cm2 length map
1539   //
1540   //  ntheta    bins in theta, eta
1541   //  themin    minimum angle in theta (degrees)
1542   //  themax    maximum angle in theta (degrees)
1543   //  nphi      bins in phi
1544   //  phimin    minimum angle in phi (degrees)
1545   //  phimax    maximum angle in phi (degrees)
1546   //  rmin      minimum radius
1547   //  rmax      maximum radius
1548   //  
1549   //
1550   //  The number of events generated = ntheta*nphi
1551   //  run input parameters in macro setup (default="Config.C")
1552   //
1553   //  Use macro "lego.C" to visualize the 3 lego plots in spherical coordinates
1554   //Begin_Html
1555   /*
1556     <img src="picts/AliRunLego1.gif">
1557   */
1558   //End_Html
1559   //Begin_Html
1560   /*
1561     <img src="picts/AliRunLego2.gif">
1562   */
1563   //End_Html
1564   //Begin_Html
1565   /*
1566     <img src="picts/AliRunLego3.gif">
1567   */
1568   //End_Html
1569   //
1570
1571   // check if initialisation has been done
1572   if (!fInitDone) InitMC(setup);
1573   //Save current generator
1574   AliGenerator *gen=Generator();
1575
1576   // Set new generator
1577   if (!gener) gener  = new AliLegoGenerator();
1578   ResetGenerator(gener);
1579   //
1580   // Configure Generator
1581   gener->SetRadiusRange(rmin, rmax);
1582   gener->SetZMax(zmax);
1583   gener->SetCoor1Range(nc1, c1min, c1max);
1584   gener->SetCoor2Range(nc2, c2min, c2max);
1585   
1586   
1587   //Create Lego object  
1588   fLego = new AliLego("lego",gener);
1589
1590   //Prepare MC for Lego Run
1591   gMC->InitLego();
1592   
1593   //Run Lego Object
1594
1595   gMC->ProcessRun(nc1*nc2+1);
1596   
1597   // Create only the Root event Tree
1598   MakeTree("E");
1599   
1600   // End of this run, close files
1601   FinishRun();
1602   // Restore current generator
1603   ResetGenerator(gen);
1604   // Delete Lego Object
1605   delete fLego; fLego=0;
1606 }
1607
1608 //_____________________________________________________________________________
1609 void AliRun::SetConfigFunction(const char * config) 
1610 {
1611   //
1612   // Set the signature of the function contained in Config.C to configure
1613   // the run
1614   //
1615   fConfigFunction=config;
1616 }
1617
1618 //_____________________________________________________________________________
1619 void AliRun::SetCurrentTrack(Int_t track)
1620
1621   //
1622   // Set current track number
1623   //
1624     fStack->SetCurrentTrack(track); 
1625 }
1626  
1627 //_____________________________________________________________________________
1628 void AliRun::SetTrack(Int_t done, Int_t parent, Int_t pdg, Float_t *pmom,
1629                       Float_t *vpos, Float_t *polar, Float_t tof,
1630                       AliMCProcess mech, Int_t &ntr, Float_t weight)
1631
1632 // Delegate to stack
1633 //
1634     fStack->SetTrack(done, parent, pdg, pmom, vpos, polar, tof,
1635                      mech, ntr, weight);
1636 }
1637
1638 //_____________________________________________________________________________
1639 void AliRun::SetTrack(Int_t done, Int_t parent, Int_t pdg,
1640                       Double_t px, Double_t py, Double_t pz, Double_t e,
1641                       Double_t vx, Double_t vy, Double_t vz, Double_t tof,
1642                       Double_t polx, Double_t poly, Double_t polz,
1643                       AliMCProcess mech, Int_t &ntr, Float_t weight)
1644
1645   // Delegate to stack
1646   //
1647     fStack->SetTrack(done, parent, pdg, px, py, pz, e, vx, vy, vz, tof,
1648                    polx, poly, polz, mech, ntr, weight);
1649     
1650 }
1651
1652 //_____________________________________________________________________________
1653 void AliRun::SetHighWaterMark(const Int_t nt)
1654 {
1655     //
1656     // Set high water mark for last track in event
1657     fStack->SetHighWaterMark(nt);
1658 }
1659
1660 //_____________________________________________________________________________
1661 void AliRun::KeepTrack(const Int_t track)
1662
1663   //
1664   // Delegate to stack
1665   //
1666     fStack->KeepTrack(track);
1667 }
1668  
1669 //_____________________________________________________________________________
1670 void AliRun::StepManager(Int_t id) 
1671 {
1672   //
1673   // Called at every step during transport
1674   //
1675
1676   //
1677   // --- If lego option, do it and leave 
1678   if (fLego)
1679     fLego->StepManager();
1680   else {
1681     Int_t copy;
1682     //Update energy deposition tables
1683     AddEnergyDeposit(gMC->CurrentVolID(copy),gMC->Edep());
1684   
1685     //Call the appropriate stepping routine;
1686     AliModule *det = (AliModule*)fModules->At(id);
1687     if(det) {
1688       fMCQA->StepManager(id);
1689       det->StepManager();
1690     }
1691   }
1692 }
1693
1694 //_____________________________________________________________________________
1695 void AliRun::Streamer(TBuffer &R__b)
1696 {
1697    // Stream an object of class AliRun.
1698
1699    if (R__b.IsReading()) {
1700       if (!gAlice) gAlice = this;
1701
1702       AliRun::Class()->ReadBuffer(R__b, this);
1703       //
1704       gROOT->GetListOfBrowsables()->Add(this,"Run");
1705
1706       fTreeE = (TTree*)gDirectory->Get("TE");
1707       if (fTreeE) {
1708           fTreeE->SetBranchAddress("Header", &fHeader);
1709       }
1710       
1711       else    Error("Streamer","cannot find Header Tree\n");
1712       fTreeE->GetEntry(0);
1713
1714       gRandom = fRandom;
1715    } else {
1716       AliRun::Class()->WriteBuffer(R__b, this);
1717    }
1718 }
1719
1720
1721 //___________________________________________________________________________
1722 Int_t AliRun::CurrentTrack() const {
1723   //
1724   // Returns current track
1725   //
1726   return fStack->CurrentTrack();
1727 }
1728
1729 //___________________________________________________________________________
1730 Int_t AliRun::GetNtrack() const {
1731   //
1732   // Returns number of tracks in stack
1733   //
1734   return fStack->GetNtrack();
1735 }
1736
1737 //___________________________________________________________________________
1738 TObjArray* AliRun::Particles() {
1739   //
1740   // Returns pointer to Particles array
1741   //
1742   return fStack->Particles();
1743 }
1744
1745 //___________________________________________________________________________
1746 TTree* AliRun::TreeK() {
1747   //
1748   // Returns pointer to the TreeK array
1749   //
1750   return fStack->TreeK();
1751 }