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