Issue AliError instead of AliFatal in case of inconsistent number of tracks
[u/mrichter/AliRoot.git] / STEER / AliDetector.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 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 // Base class for ALICE modules. Both sensitive modules (detectors) and      //
21 // non-sensitive ones are described by this base class. This class           //
22 // supports the hit and digit trees produced by the simulation and also      //
23 // the objects produced by the reconstruction.                               //
24 //                                                                           //
25 // This class is also responsible for building the geometry of the           //
26 // detectors.                                                                //
27 //                                                                           //
28 //Begin_Html
29 /*
30 <img src="picts/AliDetectorClass.gif">
31 */
32 //End_Html
33 //                                                                           //
34 ///////////////////////////////////////////////////////////////////////////////
35
36 #include <TBrowser.h>
37 #include <TTree.h>
38
39 #include "AliLog.h"
40 #include "AliConfig.h"
41 #include "AliDetector.h"
42 #include "AliHit.h"
43 #include "AliPoints.h"
44 #include "AliLoader.h"
45 #include "AliRun.h"
46 #include "AliMC.h"
47
48
49 ClassImp(AliDetector)
50  
51 //_______________________________________________________________________
52 AliDetector::AliDetector():
53   AliModule(),
54   fTimeGate(200.e-9),
55   fIshunt(0),
56   fNhits(0),
57   fNdigits(0),
58   fBufferSize(1600),
59   fMaxIterHit(0),
60   fCurIterHit(0),
61   fHits(0),
62   fDigits(0),
63   fPoints(0),
64   fLoader(0x0)
65 {
66   //
67   // Default constructor for the AliDetector class
68   //
69 }
70  
71 //_______________________________________________________________________
72 AliDetector::AliDetector(const AliDetector &det):
73   AliModule(det),
74   fTimeGate(200.e-9),
75   fIshunt(0),
76   fNhits(0),
77   fNdigits(0),
78   fBufferSize(1600),
79   fMaxIterHit(0),
80   fCurIterHit(0),
81   fHits(0),
82   fDigits(0),
83   fPoints(0),
84   fLoader(0x0)
85 {
86   det.Copy(*this);
87 }
88
89 //_____________________________________________________________________________
90 AliDetector::AliDetector(const char* name,const char *title):
91   AliModule(name,title),
92   fTimeGate(200.e-9),
93   fIshunt(0),
94   fNhits(0),
95   fNdigits(0),
96   fBufferSize(1600),
97   fMaxIterHit(0),
98   fCurIterHit(0),
99   fHits(0),
100   fDigits(0),
101   fPoints(0),
102   fLoader(0x0)
103 {
104   //
105   // Normal constructor invoked by all Detectors.
106   // Create the list for detector specific histograms
107   // Add this Detector to the global list of Detectors in Run.
108   //
109
110   fActive     = kTRUE;
111   AliConfig::Instance()->Add(this);
112
113 }
114  
115 //_______________________________________________________________________
116 AliDetector::~AliDetector()
117 {
118   //
119   // Destructor
120   //
121
122   // Delete space point structure
123   if (fPoints) {
124     fPoints->Delete();
125     delete fPoints;
126     fPoints     = 0;
127   }
128   // Delete digits structure
129   if (fDigits) {
130     fDigits->Delete();
131     delete fDigits;
132     fDigits     = 0;
133   }
134
135   if (fLoader)
136    {
137     fLoader->GetModulesFolder()->Remove(this);
138    }
139
140 }
141
142 //_______________________________________________________________________
143 void AliDetector::Publish(const char */*dir*/, void */*address*/, const char */*name*/) const
144 {
145 //
146 // Register pointer to detector objects. 
147 // 
148   MayNotUse("Publish");
149 }
150
151 //_______________________________________________________________________
152 TBranch* AliDetector::MakeBranchInTree(TTree *tree, const char* name, 
153                                        void* address, Int_t size,
154                                        const char *file)
155
156     return(MakeBranchInTree(tree,name,0,address,size,99,file));
157 }
158
159 //_______________________________________________________________________
160 TBranch* AliDetector::MakeBranchInTree(TTree *tree, const char* name, 
161                                        const char *classname, 
162                                        void* address,Int_t size, 
163                                        Int_t splitlevel, const char */*file*/)
164
165 //
166 // Makes branch in given tree and diverts them to a separate file
167 // 
168 //
169 //
170     
171  AliDebug(2,Form("Making Branch %s",name));
172  if (tree == 0x0) 
173   {
174    AliError(Form("Making Branch %s Tree is NULL",name));
175    return 0x0;
176   }
177  TBranch *branch = tree->GetBranch(name);
178  if (branch) 
179   {  
180     AliDebug(2,Form("Branch %s is already in tree.",name));
181     return branch;
182   }
183     
184  if (classname) 
185   {
186     branch = tree->Branch(name,classname,address,size,splitlevel);
187   } 
188  else 
189   {
190     branch = tree->Bronch(name, "TClonesArray", address, size, splitlevel);
191   }
192  AliDebug(2,Form("Branch %s returning branch %#x",name,branch));
193  return branch;
194 }
195
196 //_______________________________________________________________________
197 void AliDetector::Browse(TBrowser *b)
198 {
199   //
200   // Insert Detector objects in the list of objects to be browsed
201   //
202   char name[64];
203   if( fHits == 0) return;
204   TObject *obj;
205   Int_t i, nobjects;
206   //
207   nobjects = fHits->GetEntries();
208   for (i=0;i<nobjects;i++) {
209     obj = fHits->At(i);
210     sprintf(name,"%s_%d",obj->GetName(),i);
211     b->Add(obj, &name[0]);
212   }
213 }
214
215 //_______________________________________________________________________
216 void AliDetector::Copy(TObject &) const
217 {
218   //
219   // Copy *this onto det -- not implemented
220   //
221   AliFatal("Not implemented");
222 }
223
224 //_______________________________________________________________________
225 void AliDetector::FinishRun()
226 {
227   //
228   // Procedure called at the end of a run.
229   //
230 }
231
232 //_______________________________________________________________________
233 AliHit* AliDetector::FirstHit(Int_t track)
234 {
235   //
236   // Initialise the hit iterator
237   // Return the address of the first hit for track
238   // If track>=0 the track is read from disk
239   // while if track<0 the first hit of the current
240   // track is returned
241   // 
242   if(track>=0) {
243     gAlice->ResetHits(); //stupid = if N detector this method is called N times
244     TreeH()->GetEvent(track); //skowron
245   }
246   //
247   fMaxIterHit=fHits->GetEntriesFast();
248   fCurIterHit=0;
249   if(fMaxIterHit) return dynamic_cast<AliHit*>(fHits->UncheckedAt(0));
250   else            return 0;
251 }
252
253 //_______________________________________________________________________
254 AliHit* AliDetector::NextHit()
255 {
256   //
257   // Return the next hit for the current track
258   //
259   if(fMaxIterHit) {
260     if(++fCurIterHit<fMaxIterHit) 
261       return dynamic_cast<AliHit*>(fHits->UncheckedAt(fCurIterHit));
262     else        
263       return 0;
264   } else {
265     AliWarning("Hit Iterator called without calling FistHit before");
266     return 0;
267   }
268 }
269
270 //_______________________________________________________________________
271 void AliDetector::LoadPoints(Int_t)
272 {
273   //
274   // Store x, y, z of all hits in memory
275   //
276   if (fHits == 0) 
277    {
278     AliError(Form("fHits == 0. Name is %s",GetName()));
279     return;
280    }
281   //
282   Int_t nhits = fHits->GetEntriesFast();
283   if (nhits == 0) 
284    {
285 //    Error("LoadPoints","nhits == 0. Name is %s",GetName());
286     return;
287    }
288   Int_t tracks = gAlice->GetMCApp()->GetNtrack();
289   if (fPoints == 0) fPoints = new TObjArray(tracks);
290   AliHit *ahit;
291   //
292   Int_t *ntrk=new Int_t[tracks];
293   Int_t *limi=new Int_t[tracks];
294   Float_t **coor=new Float_t*[tracks];
295   for(Int_t i=0;i<tracks;i++) {
296     ntrk[i]=0;
297     coor[i]=0;
298     limi[i]=0;
299   }
300   //
301   AliPoints *points = 0;
302   Float_t *fp=0;
303   Int_t trk;
304   Int_t chunk=nhits/4+1;
305   //
306   // Loop over all the hits and store their position
307   for (Int_t hit=0;hit<nhits;hit++) {
308     ahit = dynamic_cast<AliHit*>(fHits->UncheckedAt(hit));
309     trk=ahit->GetTrack();
310     if(trk>tracks) {
311       AliError(Form("Found track number %d, max track %d",trk, tracks));
312       continue;
313     }
314     if(ntrk[trk]==limi[trk])
315      {
316       //
317       // Initialise a new track
318       fp=new Float_t[3*(limi[trk]+chunk)];
319       if(coor[trk]) 
320        {
321           memcpy(fp,coor[trk],sizeof(Float_t)*3*limi[trk]);
322           delete [] coor[trk];
323        }
324       limi[trk]+=chunk;
325       coor[trk] = fp;
326      } 
327     else 
328      {
329       fp = coor[trk];
330      }
331     fp[3*ntrk[trk]  ] = ahit->X();
332     fp[3*ntrk[trk]+1] = ahit->Y();
333     fp[3*ntrk[trk]+2] = ahit->Z();
334     ntrk[trk]++;
335   }
336   //
337   for(trk=0; trk<tracks; ++trk) {
338     if(ntrk[trk]) {
339       points = new AliPoints();
340       points->SetMarkerColor(GetMarkerColor());
341       points->SetMarkerSize(GetMarkerSize());
342       points->SetDetector(this);
343       points->SetParticle(trk);
344       points->SetPolyMarker(ntrk[trk],coor[trk],GetMarkerStyle());
345       fPoints->AddAt(points,trk);
346       delete [] coor[trk];
347       coor[trk]=0;
348     }
349   }
350   delete [] coor;
351   delete [] ntrk;
352   delete [] limi;
353 }
354
355 //_______________________________________________________________________
356 void AliDetector::MakeBranch(Option_t *option)
357 {
358   //
359   // Create a new branch for this detector in its treeH
360   //
361
362   AliDebug(2,Form(" for %s",GetName()));
363   const char *cH = strstr(option,"H");
364
365   if (fHits && TreeH() && cH) 
366    {
367      MakeBranchInTree(TreeH(), GetName(), &fHits, fBufferSize, 0);
368    }    
369 }
370
371 //_______________________________________________________________________
372 void AliDetector::ResetDigits()
373 {
374   //
375   // Reset number of digits and the digits array
376   //
377   fNdigits   = 0;
378   if (fDigits) fDigits->Clear();
379 }
380
381 //_______________________________________________________________________
382 void AliDetector::ResetHits()
383 {
384   //
385   // Reset number of hits and the hits array
386   //
387   fNhits   = 0;
388   if (fHits) fHits->Clear();
389 }
390
391 //_______________________________________________________________________
392 void AliDetector::ResetPoints()
393 {
394   //
395   // Reset array of points
396   //
397   if (fPoints) {
398     fPoints->Delete();
399     delete fPoints;
400     fPoints = 0;
401   }
402 }
403
404 //_______________________________________________________________________
405 void AliDetector::SetTreeAddress()
406 {
407   //
408   // Set branch address for the Hits and Digits Trees
409   //
410   TBranch *branch;
411   //
412   // Branch address for hit tree
413   
414   TTree *tree = TreeH();
415   if (tree && fHits) {
416     branch = tree->GetBranch(GetName());
417     if (branch) 
418      {
419        AliDebug(2,Form("(%s) Setting for Hits",GetName()));
420        branch->SetAddress(&fHits);
421      }
422     else
423      { //can be invoked before branch creation
424        AliDebug(2,Form("(%s) Failed for Hits. Can not find branch in tree.",GetName()));
425      }
426   }
427   
428   //
429   // Branch address for digit tree
430   TTree *treeD = fLoader->TreeD();
431   if (treeD && fDigits) {
432     branch = treeD->GetBranch(GetName());
433     if (branch) branch->SetAddress(&fDigits);
434   }
435   
436   AliModule::SetTreeAddress();
437 }
438
439 //_______________________________________________________________________
440 void AliDetector::MakeTree(Option_t *option)
441  {
442  //makes a tree (container) for the data defined in option
443  //"H" - hits
444  //"D" - digits
445  //"S" - summable digits
446  //"R" - recontructed points and tracks
447  
448     AliLoader* loader = GetLoader();
449     if (loader == 0x0)
450      {
451        AliError(Form("Can not get loader for %s",GetName()));
452        return;
453      }
454     loader->MakeTree(option); //delegate this job to getter
455  }
456
457 //_______________________________________________________________________
458 AliLoader* AliDetector::MakeLoader(const char* topfoldername)
459
460 //builds standard getter (AliLoader type)
461 //if detector wants to use castomized getter, it must overload this method
462
463  AliDebug(1,Form("Creating standard getter for detector %s. Top folder is %s.",
464          GetName(),topfoldername));
465      
466  fLoader = new AliLoader(GetName(),topfoldername);
467  return fLoader;
468 }
469
470 //_______________________________________________________________________
471 TTree* AliDetector::TreeH() const
472 {
473 //Get the hits container from the folder
474   if (GetLoader() == 0x0) 
475     {
476     //sunstitude this with make getter when we can obtain the event folder name 
477      AliError("Can not get the getter");
478      return 0x0;
479     }
480  
481   TTree* tree = (TTree*)GetLoader()->TreeH();
482   return tree;
483 }
484