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