]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDInput.cxx
Fixes
[u/mrichter/AliRoot.git] / FMD / AliFMDInput.cxx
1 /**************************************************************************
2  * Copyright(c) 2004, 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 /* $Id$ */
16 /** @file    AliFMDInput.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Mon Mar 27 12:42:40 2006
19     @brief   FMD utility classes for reading FMD data
20 */
21 //___________________________________________________________________
22 //
23 // The classes defined here, are utility classes for reading in data
24 // for the FMD.  They are  put in a seperate library to not polute the
25 // normal libraries.  The classes are intended to be used as base
26 // classes for customized class that do some sort of analysis on the
27 // various types of data produced by the FMD. 
28 //
29 // Latest changes by Christian Holm Christensen
30 //
31 #include "AliFMDInput.h"        // ALIFMDHIT_H
32 #include "AliFMDDebug.h"        // ALIFMDDEBUG_H ALILOG_H
33 #include "AliLoader.h"          // ALILOADER_H
34 #include "AliRunLoader.h"       // ALIRUNLOADER_H
35 #include "AliRun.h"             // ALIRUN_H
36 #include "AliStack.h"           // ALISTACK_H
37 #include "AliRawReaderFile.h"   // ALIRAWREADERFILE_H
38 #include "AliFMD.h"             // ALIFMD_H
39 #include "AliFMDHit.h"          // ALIFMDHIT_H
40 #include "AliFMDDigit.h"        // ALIFMDDigit_H
41 #include "AliFMDSDigit.h"       // ALIFMDDigit_H
42 #include "AliFMDRecPoint.h"     // ALIFMDRECPOINT_H
43 #include "AliFMDRawReader.h"    // ALIFMDRAWREADER_H
44 #include <AliESD.h>
45 #include <AliESDFMD.h>
46 #include <AliESDEvent.h>
47 #include <AliCDBManager.h>
48 #include <AliCDBEntry.h>
49 #include <AliAlignObjParams.h>
50 #include <TTree.h>              // ROOT_TTree
51 #include <TChain.h>             // ROOT_TChain
52 #include <TParticle.h>          // ROOT_TParticle
53 #include <TString.h>            // ROOT_TString
54 #include <TDatabasePDG.h>       // ROOT_TDatabasePDG
55 #include <TMath.h>              // ROOT_TMath
56 #include <TGeoManager.h>        // ROOT_TGeoManager 
57 #include <TSystemDirectory.h>   // ROOT_TSystemDirectory
58 #include <Riostream.h>          // ROOT_Riostream
59 #include <TFile.h>              // ROOT_TFile
60 #include <TStreamerInfo.h>
61 #include <TArrayF.h>
62
63 //____________________________________________________________________
64 ClassImp(AliFMDInput)
65 #if 0
66   ; // This is here to keep Emacs for indenting the next line
67 #endif
68
69
70 //____________________________________________________________________
71 AliFMDInput::AliFMDInput()
72   : fGAliceFile(""), 
73     fLoader(0),
74     fRun(0), 
75     fStack(0),
76     fFMDLoader(0), 
77     fReader(0),
78     fFMD(0),
79     fESD(0),
80     fESDEvent(0),
81     fTreeE(0),
82     fTreeH(0),
83     fTreeD(0),
84     fTreeS(0),
85     fTreeR(0), 
86     fTreeA(0), 
87     fChainE(0),
88     fArrayE(0),
89     fArrayH(0),
90     fArrayD(0),
91     fArrayS(0), 
92     fArrayR(0), 
93     fArrayA(0), 
94     fGeoManager(0),
95     fTreeMask(0), 
96     fIsInit(kFALSE)
97 {
98
99   // Constructor of an FMD input object.  Specify what data to read in
100   // using the AddLoad member function.   Sub-classes should at a
101   // minimum overload the member function Event.   A full job can be
102   // executed using the member function Run. 
103 }
104
105   
106
107 //____________________________________________________________________
108 AliFMDInput::AliFMDInput(const char* gAliceFile)
109   : fGAliceFile(gAliceFile),
110     fLoader(0),
111     fRun(0), 
112     fStack(0),
113     fFMDLoader(0), 
114     fReader(0),
115     fFMD(0),
116     fESD(0),
117     fESDEvent(0),
118     fTreeE(0),
119     fTreeH(0),
120     fTreeD(0),
121     fTreeS(0),
122     fTreeR(0), 
123     fTreeA(0), 
124     fChainE(0),
125     fArrayE(0),
126     fArrayH(0),
127     fArrayD(0),
128     fArrayS(0), 
129     fArrayR(0), 
130     fArrayA(0), 
131     fGeoManager(0),
132     fTreeMask(0), 
133     fIsInit(kFALSE)
134 {
135   
136   // Constructor of an FMD input object.  Specify what data to read in
137   // using the AddLoad member function.   Sub-classes should at a
138   // minimum overload the member function Event.   A full job can be
139   // executed using the member function Run. 
140 }
141
142 //____________________________________________________________________
143 Int_t
144 AliFMDInput::NEvents() const 
145 {
146   // Get number of events
147   if (fTreeE) return fTreeE->GetEntries();
148   return -1;
149 }
150
151 //____________________________________________________________________
152 Bool_t
153 AliFMDInput::Init()
154 {
155   // Initialize the object.  Get the needed loaders, and such. 
156
157   // Check if we have been initialized
158   if (fIsInit) { 
159     AliWarning("Already initialized");
160     return fIsInit;
161   }
162   if (fGAliceFile.IsNull()) fGAliceFile = "galice.root";
163   // Get the loader
164   fLoader = AliRunLoader::Open(fGAliceFile.Data(), "Alice", "read");
165   if (!fLoader) {
166     AliError(Form("Coulnd't read the file %s", fGAliceFile.Data()));
167     return kFALSE;
168   }
169   
170   // Get the run 
171   if  (fLoader->LoadgAlice()) return kFALSE;
172   fRun = fLoader->GetAliRun();
173   
174   // Get the FMD 
175   fFMD = static_cast<AliFMD*>(fRun->GetDetector("FMD"));
176   if (!fFMD) {
177     AliError("Failed to get detector FMD from loader");
178     return kFALSE;
179   }
180   
181   // Get the FMD loader
182   fFMDLoader = fLoader->GetLoader("FMDLoader");
183   if (!fFMDLoader) {
184     AliError("Failed to get detector FMD loader from loader");
185     return kFALSE;
186   }
187   if (fLoader->LoadHeader()) { 
188     AliError("Failed to get event header information from loader");
189     return kFALSE;
190   }
191   fTreeE = fLoader->TreeE();
192
193   // Optionally, get the ESD files
194   if (TESTBIT(fTreeMask, kESD)) {
195     fChainE = new TChain("esdTree");
196     TSystemDirectory dir(".",".");
197     TList*           files = dir.GetListOfFiles();
198     TSystemFile*     file = 0;
199     if (!files) {
200       AliError("No files");
201       return kFALSE;
202     }
203     files->Sort();
204     TIter            next(files);
205     while ((file = static_cast<TSystemFile*>(next()))) {
206       TString fname(file->GetName());
207       if (fname.Contains("AliESDs")) fChainE->AddFile(fname.Data());
208     }
209     fESDEvent = new AliESDEvent();
210     fESDEvent->ReadFromTree(fChainE);
211     //    fChainE->SetBranchAddress("ESD", &fMainESD);
212     
213   }
214     
215   if (TESTBIT(fTreeMask, kRaw)) {
216     AliInfo("Getting FMD raw data digits");
217     fArrayA = new TClonesArray("AliFMDDigit");
218     fReader = new AliRawReaderFile(-1);
219   }
220   
221   // Optionally, get the geometry 
222   if (TESTBIT(fTreeMask, kGeometry)) {
223     TString fname(fRun->GetGeometryFileName());
224     if (fname.IsNull()) {
225       Warning("Init", "No file name for the geometry from AliRun");
226       fname = gSystem->DirName(fGAliceFile);
227       fname.Append("/geometry.root");
228     }
229     fGeoManager = TGeoManager::Import(fname.Data());
230     if (!fGeoManager) {
231       Fatal("Init", "No geometry manager found");
232       return kFALSE;
233     }
234     AliCDBManager* cdb   = AliCDBManager::Instance();
235     AliCDBEntry*   align = cdb->Get("FMD/Align/Data");
236     if (align) {
237       AliInfo("Got alignment data from CDB");
238       TClonesArray* array = dynamic_cast<TClonesArray*>(align->GetObject());
239       if (!array) {
240         AliWarning("Invalid align data from CDB");
241       }
242       else {
243         Int_t nAlign = array->GetEntries();
244         for (Int_t i = 0; i < nAlign; i++) {
245           AliAlignObjParams* a = static_cast<AliAlignObjParams*>(array->At(i));
246           if (!a->ApplyToGeometry()) {
247             AliWarning(Form("Failed to apply alignment to %s", 
248                             a->GetSymName()));
249           }
250         }
251       }
252     }
253   }
254
255   fEventCount = 0;
256   fIsInit = kTRUE;
257   return fIsInit;
258 }
259
260 //____________________________________________________________________
261 Bool_t
262 AliFMDInput::Begin(Int_t event)
263 {
264   // Called at the begining of each event.  Per default, it gets the
265   // data trees and gets pointers to the output arrays.   Users can
266   // overload this, but should call this member function in the
267   // overloaded member function of the derived class. 
268
269   // Check if we have been initialized
270   if (!fIsInit) { 
271     AliError("Not initialized");
272     return fIsInit;
273   }
274
275   // Get the event 
276   if (fLoader->GetEvent(event)) return kFALSE;
277   AliInfo(Form("Now in event %8d/%8d", event, NEvents()));
278
279   // Possibly load global kinematics information 
280   if (TESTBIT(fTreeMask, kKinematics) || TESTBIT(fTreeMask, kTracks)) {
281     // AliInfo("Getting kinematics");
282     if (fLoader->LoadKinematics()) return kFALSE;
283     fStack = fLoader->Stack();
284   }
285
286   // Possibly load FMD Hit information 
287   if (TESTBIT(fTreeMask, kHits) || TESTBIT(fTreeMask, kTracks)) {
288     // AliInfo("Getting FMD hits");
289     if (!fFMDLoader || fFMDLoader->LoadHits()) return kFALSE;
290     fTreeH = fFMDLoader->TreeH();
291     if (!fArrayH) fArrayH = fFMD->Hits(); 
292   }
293
294   // Possibly load FMD Digit information 
295   if (TESTBIT(fTreeMask, kDigits)) {
296     // AliInfo("Getting FMD digits");
297     if (!fFMDLoader || fFMDLoader->LoadDigits()) return kFALSE;
298     fTreeD = fFMDLoader->TreeD();
299     if (fTreeD) {
300       if (!fArrayD) fArrayD = fFMD->Digits();
301     }
302     else {
303       fArrayD = 0;
304       AliWarning(Form("Failed to load FMD Digits"));
305     } 
306   }
307
308   // Possibly load FMD Sdigit information 
309   if (TESTBIT(fTreeMask, kSDigits)) {
310     // AliInfo("Getting FMD summable digits");
311     if (!fFMDLoader || fFMDLoader->LoadSDigits()) return kFALSE;
312     fTreeS = fFMDLoader->TreeS();
313     if (!fArrayS) fArrayS = fFMD->SDigits();
314   }
315
316   // Possibly load FMD RecPoints information 
317   if (TESTBIT(fTreeMask, kRecPoints)) {
318     // AliInfo("Getting FMD reconstructed points");
319     if (!fFMDLoader || fFMDLoader->LoadRecPoints()) return kFALSE;
320     fTreeR = fFMDLoader->TreeR();
321     if (!fArrayR) fArrayR = new TClonesArray("AliFMDRecPoint");
322     fTreeR->SetBranchAddress("FMD",  &fArrayR);
323   }  
324
325   // Possibly load FMD ESD information 
326   if (TESTBIT(fTreeMask, kESD)) {
327     // AliInfo("Getting FMD event summary data");
328     Int_t read = fChainE->GetEntry(event);
329     if (read <= 0) return kFALSE;
330     fESD = fESDEvent->GetFMDData();
331     if (!fESD) return kFALSE;
332 #if 0
333     TFile* f = fChainE->GetFile();
334     if (f) {
335       TObject* o = f->GetStreamerInfoList()->FindObject("AliFMDMap");
336       if (o) {
337         TStreamerInfo* info = static_cast<TStreamerInfo*>(o);
338         std::cout << "AliFMDMap class version read is " 
339                   <<  info->GetClassVersion() << std::endl;
340       }
341     }
342     // fESD->CheckNeedUShort(fChainE->GetFile());
343 #endif
344   }
345
346   // Possibly load FMD Digit information 
347   if (TESTBIT(fTreeMask, kRaw)) {
348     // AliInfo("Getting FMD raw data digits");
349     if (!fReader->NextEvent()) return kFALSE;
350     AliFMDRawReader r(fReader, 0);
351     fArrayA->Clear();
352     r.ReadAdcs(fArrayA);
353   }
354   fEventCount++;
355   return kTRUE;
356 }
357
358
359 //____________________________________________________________________
360 Bool_t 
361 AliFMDInput::Event()
362 {
363   // Process one event.  The default implementation one or more of 
364   //
365   //   -  ProcessHits       if the hits are loaded. 
366   //   -  ProcessDigits     if the digits are loaded. 
367   //   -  ProcessSDigits    if the sumbable digits are loaded. 
368   //   -  ProcessRecPoints  if the reconstructed points are loaded. 
369   //   -  ProcessESD        if the event summary data is loaded
370   // 
371   if (TESTBIT(fTreeMask, kHits)) 
372     if (!ProcessHits()) return kFALSE; 
373   if (TESTBIT(fTreeMask, kTracks)) 
374     if (!ProcessTracks()) return kFALSE; 
375   if (TESTBIT(fTreeMask, kDigits)) 
376     if (!ProcessDigits()) return kFALSE;
377   if (TESTBIT(fTreeMask, kSDigits)) 
378     if (!ProcessSDigits()) return kFALSE;
379   if (TESTBIT(fTreeMask, kRaw)) 
380     if (!ProcessRawDigits()) return kFALSE;
381   if (TESTBIT(fTreeMask, kRecPoints)) 
382     if (!ProcessRecPoints()) return kFALSE;
383   if (TESTBIT(fTreeMask, kESD))
384     if (!ProcessESDs()) return kFALSE;
385   
386   return kTRUE;
387 }
388
389 //____________________________________________________________________
390 Bool_t 
391 AliFMDInput::ProcessHits()
392 {
393   // Read the hit tree, and pass each hit to the member function
394   // ProcessHit.
395   if (!fTreeH) {
396     AliError("No hit tree defined");
397     return kFALSE;
398   }
399   Int_t nTracks = fTreeH->GetEntries();
400   for (Int_t i = 0; i < nTracks; i++) {
401     Int_t hitRead  = fTreeH->GetEntry(i);
402     if (hitRead <= 0) continue;
403     if (!fArrayH) {
404       AliError("No hit array defined");
405       return kFALSE;
406     }
407     Int_t nHit = fArrayH->GetEntries();
408     if (nHit <= 0) continue;
409     for (Int_t j = 0; j < nHit; j++) {
410       AliFMDHit* hit = static_cast<AliFMDHit*>(fArrayH->At(j));
411       if (!hit) continue;
412       TParticle* track = 0;
413       if (TESTBIT(fTreeMask, kKinematics) && fStack) {
414         Int_t trackno = hit->Track();
415         track = fStack->Particle(trackno);
416       }
417       if (!ProcessHit(hit, track)) return kFALSE;
418     }    
419   }
420   return kTRUE;
421 }
422
423 //____________________________________________________________________
424 Bool_t 
425 AliFMDInput::ProcessTracks()
426 {
427   // Read the hit tree, and pass each hit to the member function
428   // ProcessHit.
429   if (!fStack) {
430     AliError("No track tree defined");
431     return kFALSE;
432   }
433   if (!fTreeH) {
434     AliError("No hit tree defined");
435     return kFALSE;
436   }
437   Int_t nTracks = fTreeH->GetEntries();
438   for (Int_t i = 0; i < nTracks; i++) {
439     TParticle* track = fStack->Particle(i);
440     if (!track) continue;
441     Int_t hitRead  = fTreeH->GetEntry(i);
442     if (hitRead <= 0) continue;
443     if (!fArrayH) {
444       AliError("No hit array defined");
445       return kFALSE;
446     }
447     Int_t nHit = fArrayH->GetEntries();
448     if (nHit <= 0) continue;
449
450     for (Int_t j = 0; j < nHit; j++) {
451       AliFMDHit* hit = static_cast<AliFMDHit*>(fArrayH->At(j));
452       if (!hit) continue;
453       if (!ProcessTrack(i, track, hit)) return kFALSE;
454     }    
455     // if (!ProcessTrack(i, track, fArrayH)) return kFALSE;
456   }
457   return kTRUE;
458 }
459
460 //____________________________________________________________________
461 Bool_t 
462 AliFMDInput::ProcessDigits()
463 {
464   // Read the digit tree, and pass each digit to the member function
465   // ProcessDigit.
466   Int_t nEv = fTreeD->GetEntries();
467   for (Int_t i = 0; i < nEv; i++) {
468     Int_t digitRead  = fTreeD->GetEntry(i);
469     if (digitRead <= 0) continue;
470     Int_t nDigit = fArrayD->GetEntries();
471     if (nDigit <= 0) continue;
472     for (Int_t j = 0; j < nDigit; j++) {
473       AliFMDDigit* digit = static_cast<AliFMDDigit*>(fArrayD->At(j));
474       if (!digit) continue;
475       if (!ProcessDigit(digit)) return kFALSE;
476     }    
477   }
478   return kTRUE;
479 }
480
481 //____________________________________________________________________
482 Bool_t 
483 AliFMDInput::ProcessSDigits()
484 {
485   // Read the summable digit tree, and pass each sumable digit to the
486   // member function ProcessSdigit.
487   Int_t nEv = fTreeD->GetEntries();
488   for (Int_t i = 0; i < nEv; i++) {
489     Int_t sdigitRead  = fTreeS->GetEntry(i);
490     if (sdigitRead <= 0) continue;
491     Int_t nSdigit = fArrayS->GetEntries();
492     if (nSdigit <= 0) continue;
493     for (Int_t j = 0; j < nSdigit; j++) {
494       AliFMDSDigit* sdigit = static_cast<AliFMDSDigit*>(fArrayS->At(j));
495       if (!sdigit) continue;
496       if (!ProcessSDigit(sdigit)) return kFALSE;
497     }    
498   }
499   return kTRUE;
500 }
501
502 //____________________________________________________________________
503 Bool_t 
504 AliFMDInput::ProcessRawDigits()
505 {
506   // Read the digit tree, and pass each digit to the member function
507   // ProcessDigit.
508   Int_t nDigit = fArrayA->GetEntries();
509   if (nDigit <= 0) return kTRUE;
510   for (Int_t j = 0; j < nDigit; j++) {
511     AliFMDDigit* digit = static_cast<AliFMDDigit*>(fArrayA->At(j));
512     if (!digit) continue;
513     if (!ProcessRawDigit(digit)) return kFALSE;
514   }    
515   return kTRUE;
516 }
517
518 //____________________________________________________________________
519 Bool_t 
520 AliFMDInput::ProcessRecPoints()
521 {
522   // Read the reconstrcted points tree, and pass each reconstruction
523   // object (AliFMDRecPoint) to either ProcessRecPoint.
524   Int_t nEv = fTreeR->GetEntries();
525   for (Int_t i = 0; i < nEv; i++) {
526     Int_t recRead  = fTreeR->GetEntry(i);
527     if (recRead <= 0) continue;
528     Int_t nRecPoint = fArrayR->GetEntries();
529     for (Int_t j = 0; j < nRecPoint; j++) {
530       AliFMDRecPoint* recPoint = static_cast<AliFMDRecPoint*>(fArrayR->At(j));
531       if (!recPoint) continue;
532       if (!ProcessRecPoint(recPoint)) return kFALSE;
533     }    
534   }
535   return kTRUE;
536 }
537
538 //____________________________________________________________________
539 Bool_t 
540 AliFMDInput::ProcessESDs()
541 {
542   // Process event summary data
543   if (!fESD) return kFALSE;
544   for (UShort_t det = 1; det <= 3; det++) {
545     Char_t rings[] = { 'I', (det == 1 ? '\0' : 'O'), '\0' };
546     for (Char_t* rng = rings; *rng != '\0'; rng++) {
547       UShort_t nsec = (*rng == 'I' ?  20 :  40);
548       UShort_t nstr = (*rng == 'I' ? 512 : 256);
549       for (UShort_t sec = 0; sec < nsec; sec++) {
550         for (UShort_t str = 0; str < nstr; str++) {
551           Float_t eta  = fESD->Eta(det,*rng,sec,str);
552           Float_t mult = fESD->Multiplicity(det,*rng,sec,str);
553           if (!fESD->IsAngleCorrected()) 
554             mult *= TMath::Abs(TMath::Cos(2.*TMath::ATan(TMath::Exp(-eta))));
555           if (!ProcessESD(det, *rng, sec, str, eta, mult)) continue;
556         }
557       }
558     }
559   }
560   return kTRUE;
561 }
562
563 //____________________________________________________________________
564 Bool_t
565 AliFMDInput::End()
566 {
567   // Called at the end of each event.  Per default, it unloads the
568   // data trees and resets the pointers to the output arrays.   Users
569   // can overload this, but should call this member function in the
570   // overloaded member function of the derived class. 
571
572   // Check if we have been initialized
573   if (!fIsInit) { 
574     AliError("Not initialized");
575     return fIsInit;
576   }
577   // Possibly unload global kinematics information 
578   if (TESTBIT(fTreeMask, kKinematics) || TESTBIT(fTreeMask, kTracks)) {
579     fLoader->UnloadKinematics();
580     // fTreeK = 0;
581     fStack = 0;
582   }
583   // Possibly unload FMD Hit information 
584   if (TESTBIT(fTreeMask, kHits) || TESTBIT(fTreeMask, kTracks)) {
585     fFMDLoader->UnloadHits();
586     fTreeH = 0;
587   }
588   // Possibly unload FMD Digit information 
589   if (TESTBIT(fTreeMask, kDigits)) {
590     fFMDLoader->UnloadDigits();
591     fTreeD = 0;
592   }
593   // Possibly unload FMD Sdigit information 
594   if (TESTBIT(fTreeMask, kSDigits)) {
595     fFMDLoader->UnloadSDigits();
596     fTreeS = 0;
597   }
598   // Possibly unload FMD RecPoints information 
599   if (TESTBIT(fTreeMask, kRecPoints)) {
600     fFMDLoader->UnloadRecPoints();
601     fTreeR = 0;
602   }
603   AliInfo("Now out event");
604   return kTRUE;
605 }
606
607 //____________________________________________________________________
608 Bool_t
609 AliFMDInput::Run()
610 {
611   // Run over all events and files references in galice.root 
612
613   Bool_t retval;
614   if (!(retval = Init())) return retval;
615
616   Int_t nEvents = NEvents();
617   for (Int_t event = 0; event < nEvents; event++) {
618     if (!(retval = Begin(event))) break;
619     if (!(retval = Event())) break;
620     if (!(retval = End())) break;
621   }
622   if (!retval) return retval;
623   retval = Finish();
624   return retval;
625 }
626
627 //__________________________________________________________________
628 TArrayF 
629 AliFMDInput::MakeLogScale(Int_t n, Double_t min, Double_t max) 
630 {
631   // Service function to define a logarithmic axis. 
632   // Parameters: 
633   //   n    Number of bins 
634   //   min  Minimum of axis 
635   //   max  Maximum of axis 
636   TArrayF bins(n+1);
637   bins[0]      = min;
638   if (n <= 20) {
639     for (Int_t i = 1; i < n+1; i++) bins[i] = bins[i-1] + (max-min)/n;
640     return bins;
641   }
642   Float_t dp   = n / TMath::Log10(max / min);
643   Float_t pmin = TMath::Log10(min);
644   for (Int_t i = 1; i < n+1; i++) {
645     Float_t p = pmin + i / dp;
646     bins[i]   = TMath::Power(10, p);
647   }
648   return bins;
649 }
650
651
652
653 //____________________________________________________________________
654 //
655 // EOF
656 //