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