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