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