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