Implemented a new version of cluster (with its store and iterator):
[u/mrichter/AliRoot.git] / MUON / AliMUONDataInterface.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15  
16 /* $Id$ */
17
18 #include "AliMUONDataInterface.h"
19 #include "AliMUONGeometryTransformer.h"
20 #include "AliMUONVDigit.h"
21 #include "AliMUONVCluster.h"
22 #include "AliMUONTrack.h"
23 #include "AliMUONLocalTrigger.h"
24 #include "AliMUONRegionalTrigger.h"
25 #include "AliMUONGlobalTrigger.h"
26 #include "AliMUONTriggerTrack.h"
27 #include "AliMUONTriggerCircuit.h"
28 #include "AliMUONVClusterStore.h"
29 #include "AliMUONVDigitStore.h"
30 #include "AliMUONVTrackStore.h"
31 #include "AliMUONVTriggerStore.h"
32 #include "AliMUONVTriggerTrackStore.h"
33 #include "AliMpCDB.h"
34
35 #include "AliMpIntPair.h"
36 #include "AliMpDEManager.h"
37 #include "AliMpConstants.h"
38 #include "AliMpCDB.h"
39
40 #include "AliLoader.h"
41 #include "AliLog.h"
42 #include "AliRunLoader.h"
43
44 #include <TError.h>
45 #include <TParticle.h>
46 #include <Riostream.h>
47 #include <TFile.h>
48 #include <TList.h>
49 #include <TNtuple.h>
50 #include <TSystem.h>
51 #include <TIterator.h>
52 #include <cstdlib>
53 #include <cassert>
54
55 //-----------------------------------------------------------------------------
56 /// \class AliMUONDataInterface
57 ///
58 /// An easy to use interface to the MUON data data stored in
59 /// TreeS, TreeD, TreeR and TreeT.
60 ///
61 /// For MC related information (i.e. TreeH, TreeK, TreeTR), see
62 /// AliMUONMCDataInterface.
63 ///
64 ///
65 /// This interface in not necessarily the fastest way to fetch the data but
66 /// it is the easiest.
67 ///
68 /// \author Laurent Aphecetche, Subatech & Artur Szostak <artursz@iafrica.com> (University of Cape Town)
69 //-----------------------------------------------------------------------------
70
71 /// \cond CLASSIMP
72 ClassImp(AliMUONDataInterface)
73 /// \endcond
74
75
76 Int_t AliMUONDataInterface::fgInstanceCounter(0);
77
78 //______________________________________________________________________________
79 AliMUONDataInterface::AliMUONDataInterface(const char* filename)
80 : TObject(), 
81 fLoader(0x0),
82 fDigitStore(0x0),
83 fTriggerStore(0x0),
84 fClusterStore(0x0),
85 fTrackStore(0x0),
86 fTriggerTrackStore(0x0),
87 fCurrentEvent(-1),
88 fIsValid(kFALSE),
89 fCurrentIteratorType(kNoIterator),
90 fCurrentIndex(-1),
91 fDataX(-1),
92 fDataY(-1),
93 fIterator(0x0)
94 {
95   /// ctor
96   /// @param filename should be the full path to a valid galice.root file
97   
98   ++fgInstanceCounter;
99   
100   Open(filename);
101
102   // Load mapping
103   if ( ! AliMpCDB::LoadDDLStore() ) {
104     AliFatal("Could not access mapping from OCDB !");
105   }
106 }
107
108 //______________________________________________________________________________
109 AliMUONDataInterface::~AliMUONDataInterface()
110 {
111   /// dtor
112   ResetStores();
113   if ( fLoader != 0x0 ) 
114   {
115     delete fLoader->GetRunLoader();
116   }
117   --fgInstanceCounter;  
118 }
119
120 //______________________________________________________________________________
121 AliMUONVDigitStore*
122 AliMUONDataInterface::DigitStore(Int_t event)
123 {
124   /// Return digitStore for a given event.
125   /// Return 0x0 if event not found.
126   /// Returned pointer should not be deleted
127   
128   if (not IsValid()) return 0x0;
129   if (event == fCurrentEvent and fDigitStore != 0x0) return fDigitStore;
130   
131   ResetStores();
132   if (not LoadEvent(event)) return 0x0;
133   
134   fLoader->LoadDigits();
135   
136   TTree* treeD = fLoader->TreeD();
137   if (treeD == 0x0)
138   {
139     AliError("Could not get treeD");
140     return 0x0;
141   }
142   
143   fDigitStore = AliMUONVDigitStore::Create(*treeD);
144   if ( fDigitStore != 0x0 ) 
145   {
146     fDigitStore->Clear();
147     fDigitStore->Connect(*treeD);
148     treeD->GetEvent(0);
149   }
150   
151   fLoader->UnloadDigits();
152   
153   return fDigitStore;
154 }
155
156 //______________________________________________________________________________
157 AliMUONVClusterStore*
158 AliMUONDataInterface::ClusterStore(Int_t event)
159 {
160   /// Return clusterStore for a given event.
161   /// Return 0x0 if event not found.
162   /// Returned pointer should not be deleted
163   
164   if (not IsValid()) return 0x0;
165   if (event == fCurrentEvent and fClusterStore != 0x0) return fClusterStore;
166   
167   ResetStores();
168   if (not LoadEvent(event)) return 0x0;
169   
170   fLoader->LoadRecPoints();
171   
172   TTree* treeR = fLoader->TreeR();
173   if (treeR == 0x0)
174   {
175     AliError("Could not get treeR");
176     return 0x0;
177   }
178   
179   fClusterStore = AliMUONVClusterStore::Create(*treeR);
180   if ( fClusterStore != 0x0 ) 
181   {
182     fClusterStore->Clear();
183     fClusterStore->Connect(*treeR);
184     treeR->GetEvent(0);
185   }
186   
187   fLoader->UnloadRecPoints();
188   
189   return fClusterStore;
190 }
191
192 //______________________________________________________________________________
193 AliMUONVTrackStore* 
194 AliMUONDataInterface::TrackStore(Int_t event)
195 {
196   /// Return the trackStore for a given event.
197   /// Return 0x0 if event not found.
198   /// Returned pointer should not be deleted
199   
200   if (not IsValid()) return 0x0;
201   if (event == fCurrentEvent and fTrackStore != 0x0) return fTrackStore;
202   
203   ResetStores();
204   if (not LoadEvent(event)) return 0x0;
205   
206   fLoader->LoadTracks();
207   
208   TTree* treeT = fLoader->TreeT();
209   if (treeT == 0x0)
210   {
211     AliError("Could not get treeT");
212     return 0x0;
213   }
214   
215   fTrackStore = AliMUONVTrackStore::Create(*treeT);
216   if ( fTrackStore != 0x0 )
217   {
218     fTrackStore->Clear();
219     fTrackStore->Connect(*treeT);
220     treeT->GetEvent(0);
221   }
222   
223   fLoader->UnloadTracks();
224   
225   return fTrackStore;
226 }
227
228 //______________________________________________________________________________
229 AliMUONVTriggerTrackStore* 
230 AliMUONDataInterface::TriggerTrackStore(Int_t event)
231 {
232   /// Return the triggerTrackStore for a given event.
233   /// Return 0x0 if event not found.
234   /// Returned pointer should not be deleted
235   
236   if (not IsValid()) return 0x0;
237   if (event == fCurrentEvent and fTriggerTrackStore != 0x0) return fTriggerTrackStore;
238   
239   ResetStores();
240   if (not LoadEvent(event)) return 0x0;
241   
242   fLoader->LoadTracks();
243   
244   TTree* treeT = fLoader->TreeT();
245   if (treeT == 0x0)
246   {
247     AliError("Could not get treeT");
248     return 0x0;
249   }
250   
251   fTriggerTrackStore = AliMUONVTriggerTrackStore::Create(*treeT);
252   if ( fTriggerTrackStore != 0x0 ) 
253   {
254     fTriggerTrackStore->Clear();
255     fTriggerTrackStore->Connect(*treeT);
256     treeT->GetEvent(0);
257   }
258   
259   fLoader->UnloadTracks();
260   
261   return fTriggerTrackStore;  
262 }
263
264 //_____________________________________________________________________________
265 AliMUONVTriggerStore*
266 AliMUONDataInterface::TriggerStore(Int_t event, const char* treeLetter)
267 {
268   /// Return the triggerStore for a given event.
269   /// Return 0x0 if event not found.
270   /// Returned pointer should not be deleted
271   /// treeLetter can be R or D to tell from which tree to read the information
272   
273   if (not IsValid()) return 0x0;
274   if (event == fCurrentEvent and fTriggerStore != 0x0) return fTriggerStore;
275   
276   ResetStores();
277   if (not LoadEvent(event)) return 0x0;
278   
279   TTree* tree(0x0);
280   
281   TString stree(treeLetter);
282   stree.ToUpper();
283   
284   if ( stree == "D" )
285   {
286     fLoader->LoadDigits();    
287     tree = fLoader->TreeD();
288   }
289   else if ( stree == "R" )
290   {
291     fLoader->LoadRecPoints();
292     tree = fLoader->TreeR();
293   }
294   
295   if ( tree == 0x0 ) 
296   {
297     AliError(Form("Could not get tree%s",treeLetter));
298     return 0x0;
299   }
300   
301   fTriggerStore = AliMUONVTriggerStore::Create(*tree);
302   if ( fTriggerStore != 0x0 ) 
303   {
304     fTriggerStore->Clear();
305     fTriggerStore->Connect(*tree);
306     tree->GetEvent(0);
307   }
308   
309   if ( stree == "D" )
310   {
311     fLoader->UnloadDigits();    
312   }
313   else if ( stree == "R" )
314   {
315     fLoader->UnloadRecPoints();
316   }
317   
318   return fTriggerStore;
319 }
320
321 //______________________________________________________________________________
322 void
323 AliMUONDataInterface::DumpDigits(Int_t event, Bool_t sorted)
324 {
325   /// Dump the digits for a given event, sorted if so required
326   DigitStore(event);
327   if ( fDigitStore != 0x0 ) 
328   {
329     if ( sorted ) 
330     {
331       DumpSorted(*fDigitStore);
332     }
333     else
334     {
335       fDigitStore->Print();
336     }
337   }
338 }
339
340 //______________________________________________________________________________
341 void
342 AliMUONDataInterface::DumpRecPoints(Int_t event, Bool_t sorted)
343 {
344   /// Dump the recpoints for a given event, sorted if so required
345   ClusterStore(event);
346   if ( fClusterStore != 0x0 ) 
347   {
348     if ( sorted ) 
349     {
350       DumpSorted(*fClusterStore);
351     }
352     else
353     {
354       fClusterStore->Print();
355     }
356   }
357 }
358
359 //_____________________________________________________________________________
360 void
361 AliMUONDataInterface::DumpSorted(const AliMUONVStore& store) const
362 {
363   /// Dump the given store, in sorted order
364   
365   TIter next(store.CreateIterator());
366   TObject* object;
367   TList list;
368   list.SetOwner(kFALSE);
369   
370   while ( ( object = next() ) )
371   {
372     list.Add(object);
373   }
374   
375   list.Sort();
376   
377   list.Print();
378 }
379
380 //______________________________________________________________________________
381 void
382 AliMUONDataInterface::DumpTracks(Int_t event, Bool_t sorted)
383 {
384   /// Dump tracks for a given event, sorted if requested
385   
386   TrackStore(event);
387   
388   if ( fTrackStore != 0x0 ) 
389   {
390     if ( sorted ) 
391     {
392       DumpSorted(*fTrackStore);
393     }
394     else
395     {
396       fTrackStore->Print();
397     }
398   }
399 }
400
401 //______________________________________________________________________________
402 void
403 AliMUONDataInterface::DumpTriggerTracks(Int_t event, Bool_t sorted)
404 {
405   /// Dump trigger tracks for a given event, sorted if requested
406
407   TriggerTrackStore(event);
408   
409   if ( fTriggerTrackStore != 0x0 ) 
410   {
411     if ( sorted ) 
412     {
413       DumpSorted(*fTriggerTrackStore);
414     }
415     else
416     {
417       fTriggerTrackStore->Print();
418     }
419   }
420 }
421
422 //_____________________________________________________________________________
423 void
424 AliMUONDataInterface::DumpTrigger(Int_t event, const char* treeLetter)
425 {
426   /// Dump trigger for a given event from a given tree (if event>=0)
427   /// or loop over all events and build a trigger ntuple if event<0
428   /// treeLetter can be R or D to tell from which tree to read the information
429   
430   if ( event < 0 ) 
431   {
432     NtupleTrigger(treeLetter);
433   }
434   else
435   {
436     TriggerStore(event,treeLetter);
437   
438     if ( fTriggerStore != 0x0 ) 
439     {
440       fTriggerStore->Print();
441     }
442   }
443 }
444
445 //_____________________________________________________________________________
446 void
447 AliMUONDataInterface::NtupleTrigger(const char* treeLetter)
448 {
449   //// Loop over events to build trigger ntuples
450   ///
451   
452   TString sTreeLetter(treeLetter);
453   sTreeLetter.ToUpper();
454   
455   if ( sTreeLetter != "R" && sTreeLetter != "D" ) 
456   {
457     AliError(Form("Cannot handle tree%s. Use D or R",treeLetter));
458     return;
459   }
460   
461   // book ntuples
462   TNtuple tupleGlo("TgtupleGlo","Global Trigger Ntuple",
463                    "ev:slpt:shpt:uplpt:uphpt:lplpt:lplpt");
464   TNtuple tupleLoc("TgtupleLoc","Local Trigger Ntuple",
465                    "ev:LoCircuit:LoStripX:LoDev:StripY:LoLpt:LoHpt:y11:y21:x11");
466   
467   // initialize counters
468   Int_t sLowpt=0;
469   Int_t sHighpt=0;
470   Int_t uSLowpt=0;
471   Int_t uSHighpt=0;
472   Int_t lSLowpt=0;
473   Int_t lSHighpt=0;
474   
475   AliMUONGeometryTransformer transformer;
476   transformer.LoadGeometryData(Form("%s/geometry.root",
477                                     gSystem->DirName(fLoader->GetRunLoader()->GetFileName())));
478     AliMUONTriggerCircuit triggerCircuit(&transformer);
479
480   // select output file name from selected Tree
481   Char_t fileNameOut[30];
482   if (sTreeLetter == "D") 
483   {
484     AliInfo(Form("reading from Digits\n"));
485     sprintf(fileNameOut,"TriggerCheckFromDigits.root");
486   } 
487   else if (sTreeLetter == "R") 
488   {
489     AliInfo(Form("reading from RecPoints\n"));
490     sprintf(fileNameOut,"TriggerCheckFromRP.root");
491   }
492   
493   // loop on events
494   Int_t nevents = NumberOfEvents();
495
496   for (Int_t ievent=0; ievent<nevents; ++ievent) 
497   {
498     if (ievent%100==0) AliInfo(Form("Processing event %d\n",ievent));
499     
500     AliMUONVTriggerStore* triggerStore = TriggerStore(ievent);
501     
502     if (!triggerStore)
503     {
504       AliError(Form("Could not read %s from tree%s","Trigger",treeLetter));
505       return;
506     }
507     
508     // get global trigger info
509     AliMUONGlobalTrigger* gloTrg = triggerStore->Global();      
510     sLowpt+=gloTrg->SingleLpt();
511     sHighpt+=gloTrg->SingleHpt();
512     uSLowpt+=gloTrg->PairUnlikeLpt(); 
513     uSHighpt+=gloTrg->PairUnlikeHpt();
514     lSLowpt+=gloTrg->PairLikeLpt(); 
515     lSHighpt+=gloTrg->PairLikeHpt();
516     
517     // loop on local triggers   
518     TIter next(triggerStore->CreateIterator());
519     AliMUONLocalTrigger* locTrg(0x0);
520     while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
521     {
522       Bool_t xTrig=kFALSE;
523       Bool_t yTrig=kFALSE;
524       
525       if ( locTrg->LoSdev()==1 && locTrg->LoDev()==0 && 
526            locTrg->LoStripX()==0) xTrig=kFALSE; // no trigger in X
527       else xTrig=kTRUE;                         // trigger in X
528       if (locTrg->LoTrigY()==1 && 
529           locTrg->LoStripY()==15 ) yTrig = kFALSE; // no trigger in Y
530       else yTrig = kTRUE;                          // trigger in Y
531       
532       if (xTrig && yTrig) 
533       { // fill ntuple if trigger in X and Y                    
534         tupleLoc.Fill(ievent,locTrg->LoCircuit(),
535                        locTrg->LoStripX(),
536                        locTrg->LoDev(),
537                        locTrg->LoStripY(),
538                        locTrg->LoLpt(),
539                        locTrg->LoHpt(),
540                        triggerCircuit.GetY11Pos(locTrg->LoCircuit(),locTrg->LoStripX()),
541                        triggerCircuit.GetY21Pos(locTrg->LoCircuit(),locTrg->LoStripX()+locTrg->LoDev()+1),
542                        triggerCircuit.GetX11Pos(locTrg->LoCircuit(),locTrg->LoStripY()));
543       }
544       tupleGlo.Fill(ievent,gloTrg->SingleLpt(),gloTrg->SingleHpt(),
545                      gloTrg->PairUnlikeLpt(),gloTrg->PairUnlikeHpt(),
546                      gloTrg->PairLikeLpt(),gloTrg->PairLikeHpt());
547     } // end of loop on local triggers
548   } // end of loop on events
549   
550   // print info and store ntuples
551   printf("\n");
552   printf("=============================================\n");
553   printf("================  SUMMARY  ==================\n");
554   printf("\n");
555   printf("Total number of events processed %d \n",nevents);
556   printf("\n");
557   printf(" Global Trigger output       Low pt  High pt\n");
558   printf(" number of Single           :\t");
559   printf("%i\t%i\t",sLowpt,sHighpt);
560   printf("\n");
561   printf(" number of UnlikeSign pair  :\t"); 
562   printf("%i\t%i\t",uSLowpt,uSHighpt);
563   printf("\n");
564   printf(" number of LikeSign pair    :\t");  
565   printf("%i\t%i\t",lSLowpt,lSHighpt);
566   printf("\n");
567   printf("=============================================\n");
568   fflush(stdout);    
569   
570   TFile myFile(fileNameOut, "RECREATE");
571   tupleGlo.Write();
572   tupleLoc.Write();
573   myFile.Close();
574 }
575
576 //_____________________________________________________________________________
577 Bool_t
578 AliMUONDataInterface::LoadEvent(Int_t event)
579 {
580   /// Load event if different from the current one.
581   /// Returns kFALSE on error and kTRUE if the event was loaded.
582   
583   assert( IsValid() );
584   
585   AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
586   if (fLoader->GetRunLoader()->GetEvent(event) == 0)
587   {
588     fCurrentEvent = event;
589     return kTRUE;
590   }
591   else
592     return kFALSE;
593 }
594
595 //______________________________________________________________________________
596 Int_t
597 AliMUONDataInterface::NumberOfEvents() const
598 {
599   /// Number of events in the current galice.root file we're attached to 
600   if (not IsValid()) return -1;
601   return fLoader->GetRunLoader()->GetNumberOfEvents();
602 }
603
604 //_____________________________________________________________________________
605 void
606 AliMUONDataInterface::Open(const char* filename)
607 {
608   /// Connect to a given galice.root file
609   
610   ResetStores();
611   
612   fCurrentEvent=-1;
613   
614   if ( fLoader != 0x0 ) 
615   {
616     delete fLoader->GetRunLoader();
617   }
618   
619   fLoader = 0x0;
620   
621   fIsValid = kTRUE;
622   
623   TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
624   
625   while (AliRunLoader::GetRunLoader(foldername) != 0x0) 
626   {
627     delete AliRunLoader::GetRunLoader(foldername);
628   }
629   
630   AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
631   if (runLoader == 0x0) 
632   {
633     AliError(Form("Cannot open file %s",filename));    
634     fIsValid = kFALSE;
635   }
636   fLoader = runLoader->GetDetectorLoader("MUON");
637   if (fLoader == 0x0) 
638   {
639     AliError("Cannot get AliMUONLoader");
640     fIsValid = kFALSE;
641   }
642   
643   if (not IsValid())
644   {
645     AliError(Form("Could not access %s filename. Object is unuseable",filename));
646   }
647 }
648
649 //_____________________________________________________________________________
650 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
651 {
652 /// Loads all reconstructed data for the given event.
653
654   if (DigitStore(event) == 0x0) return kFALSE;
655   if (ClusterStore(event) == 0x0) return kFALSE;
656   if (TrackStore(event) == 0x0) return kFALSE;
657   if (TriggerStore(event) == 0x0) return kFALSE;
658   if (TriggerTrackStore(event) == 0x0) return kFALSE;
659   return kTRUE;
660 }
661
662 //_____________________________________________________________________________
663 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
664 {
665 /// Returns the number of digits to be found on a given detector element.
666 /// @param detElemId  The detector element ID number to search on.
667
668   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
669   return CountObjects(iter);
670 }
671
672 //_____________________________________________________________________________
673 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
674 {
675 /// Returns the a pointer to the index'th digit on the specified detector element.
676 /// @param detElemId  The detector element ID number to search on.
677 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
678 ///   where N = NumberOfDigits(detElemId)
679
680   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
681   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
682 }
683
684 //_____________________________________________________________________________
685 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
686 {
687 /// Returns the number of digits to be found on a specific chamber and cathode.
688 /// @param chamber  The chamber number in the range [0 .. 13].
689 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
690 ///   1 is the non-bending plane.
691
692   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
693   return CountObjects(iter);
694 }
695
696 //_____________________________________________________________________________
697 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
698 {
699 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
700 /// @param chamber  The chamber number in the range [0 .. 13].
701 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
702 ///   1 is the non-bending plane.
703 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
704 ///   where N = NumberOfDigits(chamber, cathode)
705
706   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
707   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
708 }
709
710 //_____________________________________________________________________________
711 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
712 {
713 /// Returns the number of reconstructed raw clusters on the specified chamber.
714 /// @param chamber  The chamber number in the range [0 .. 13].
715
716   TIterator* iter = GetIterator(kRawClusterIterator, chamber);
717   return CountObjects(iter);
718 }
719
720 //_____________________________________________________________________________
721 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
722 {
723 /// Returns a pointer to the index'th raw cluster on the specified chamber.
724 /// @param chamber  The chamber number in the range [0 .. 13].
725 /// @param index  The index number of the raw cluster to fetch in the range [0 .. N-1],
726 ///   where N = NumberOfRawClusters(chamber)
727
728   TIterator* iter = GetIterator(kRawClusterIterator, chamber);
729   return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
730 }
731
732 //_____________________________________________________________________________
733 Int_t AliMUONDataInterface::NumberOfTracks()
734 {
735 /// Returns the number of reconstructed tracks.
736
737   TIterator* iter = GetIterator(kTrackIterator);
738   return CountObjects(iter);
739 }
740
741 //_____________________________________________________________________________
742 AliMUONTrack* AliMUONDataInterface::Track(Int_t index)
743 {
744 /// Returns a pointer to the index'th reconstructed track.
745 /// @param index  The index number of the track to fetch in the range [0 .. N-1],
746 ///   where N = NumberOfTracks()
747
748   TIterator* iter = GetIterator(kTrackIterator);
749   return static_cast<AliMUONTrack*>( FetchObject(iter, index) );
750 }
751
752 //_____________________________________________________________________________
753 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
754 {
755 /// Returns the number of reconstructed local trigger objects.
756
757   TIterator* iter = GetIterator(kLocalTriggerIterator);
758   return CountObjects(iter);
759 }
760
761 //_____________________________________________________________________________
762 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
763 {
764 /// Returns a pointer to the index'th local trigger object.
765 /// @param index  The index number of the local trigger object to fetch in the range [0 .. N-1],
766 ///   where N = NumberOfLocalTriggers()
767
768   TIterator* iter = GetIterator(kLocalTriggerIterator);
769   return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
770 }
771
772 //_____________________________________________________________________________
773 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
774 {
775 /// Returns the number of regional trigger objects reconstructed.
776
777   TIterator* iter = GetIterator(kRegionalTriggerIterator);
778   return CountObjects(iter);
779 }
780
781 //_____________________________________________________________________________
782 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
783 {
784 /// Returns a pointer to the index'th regional trigger object.
785 /// @param index  The index number of the regional trigger object to fetch in the range [0 .. N-1],
786 ///   where N = NumberOfRegionalTriggers()
787
788   TIterator* iter = GetIterator(kRegionalTriggerIterator);
789   return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
790 }
791
792 //_____________________________________________________________________________
793 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
794 {
795 /// Returns a pointer to the reconstructed global trigger object for the event.
796
797   AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
798   if (store == 0x0) return 0x0;
799   return store->Global();
800 }
801
802 //_____________________________________________________________________________
803 Int_t AliMUONDataInterface::NumberOfTriggerTracks()
804 {
805 /// Returns the number of reconstructed tracks in the trigger chambers.
806
807   TIterator* iter = GetIterator(kTriggerTrackIterator);
808   return CountObjects(iter);
809 }
810
811 //_____________________________________________________________________________
812 AliMUONTriggerTrack* AliMUONDataInterface::TriggerTrack(Int_t index)
813 {
814 /// Returns a pointer to the index'th reconstructed trigger track object.
815 /// @param index  The index number of the trigger track to fetch in the range [0 .. N-1],
816 ///   where N = NumberOfTriggerTracks()
817
818   TIterator* iter = GetIterator(kTriggerTrackIterator);
819   return static_cast<AliMUONTriggerTrack*>( FetchObject(iter, index) );
820 }
821
822 //_____________________________________________________________________________
823 void AliMUONDataInterface::ResetStores()
824 {
825 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
826 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
827
828   ResetIterator();
829   if (fDigitStore != 0x0)
830   {
831     delete fDigitStore;
832     fDigitStore = 0x0;
833   }
834   if (fTriggerStore != 0x0)
835   {
836     delete fTriggerStore;
837     fTriggerStore = 0x0;
838   }
839   if (fClusterStore != 0x0)
840   {
841     delete fClusterStore;
842     fClusterStore = 0x0;
843   }
844   if (fTrackStore != 0x0)
845   {
846     delete fTrackStore;
847     fTrackStore = 0x0;
848   }
849   if (fTriggerTrackStore != 0x0)
850   {
851     delete fTriggerTrackStore;
852     fTriggerTrackStore = 0x0;
853   }
854 }
855
856 //_____________________________________________________________________________
857 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
858 {
859 /// Creates an appropriate iterator object and returns it.
860 /// If the iterator has already been created then that one is returned otherwise
861 /// a new object is created.
862 /// Depending on the value of 'type' the semantics of parameters x and y can change.
863 /// @param type  The type of iterator to create.
864 /// @param x  This is the detector element ID if type == kDigitIteratorByDetectorElement
865 ///           If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
866 ///           then this is the chamber number. In all other cases this parameter is
867 ///           ignored.
868 /// @param y  If type == kDigitIteratorByChamberAndCathode then this parameter is the
869 ///           cathode number. In all other cases this parameter is
870 ///           ignored.
871
872   if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
873         return fIterator;
874   
875   if (fCurrentEvent == -1)
876   {
877     AliError("No event was selected. Try first using GetEvent().");
878     return 0x0;
879   }
880   
881   ResetIterator();
882   
883   switch (type)
884   {
885   case kDigitIteratorByDetectorElement:
886     {
887       Int_t detElem = x;
888       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
889       if (store == 0x0) return 0x0;
890       fIterator = store->CreateIterator(detElem, detElem, 2);
891       if (fIterator == 0x0) return 0x0;
892       fCurrentIteratorType = kDigitIteratorByDetectorElement;
893       fDataX = detElem;
894       return fIterator;
895     }
896     
897   case kDigitIteratorByChamberAndCathode:
898     {
899       Int_t chamber = x;
900       Int_t cathode = y;
901       if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
902       {
903         AliError(Form(
904           "Must have give a chamber value in the range [0..%d], but got a value of: %d",
905           AliMpConstants::NofChambers() - 1,
906           chamber
907         ));
908         return 0x0;
909       }
910       if (cathode < 0 or 1 < cathode)
911       {
912         AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
913         return 0x0;
914       }
915       
916       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
917       if (store == 0x0) return 0x0;
918       AliMpIntPair pair = AliMpDEManager::GetDetElemIdRange(chamber);
919       fIterator = store->CreateIterator(pair.GetFirst(), pair.GetSecond(), cathode);
920       if (fIterator == 0x0) return 0x0;
921       fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
922       fDataX = chamber;
923       fDataY = cathode;
924       return fIterator;
925     }
926     
927   case kRawClusterIterator:
928     {
929       Int_t chamber = x;
930       AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
931       if (store == 0x0) return 0x0;
932       fIterator = store->CreateChamberIterator(chamber, chamber);
933       if (fIterator == 0x0) return 0x0;
934       fCurrentIteratorType = kRawClusterIterator;
935       fDataX = chamber;
936       return fIterator;
937     }
938     
939   case kTrackIterator:
940     {
941       AliMUONVTrackStore* store = TrackStore(fCurrentEvent);
942       if (store == 0x0) return 0x0;
943       fIterator = store->CreateIterator();
944       if (fIterator == 0x0) return 0x0;
945       fCurrentIteratorType = kTrackIterator;
946       return fIterator;
947     }
948     
949   case kLocalTriggerIterator:
950     {
951       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
952       if (store == 0x0) return 0x0;
953       fIterator = store->CreateLocalIterator();
954       if (fIterator == 0x0) return 0x0;
955       fCurrentIteratorType = kLocalTriggerIterator;
956       return fIterator;
957     }
958     
959   case kRegionalTriggerIterator:
960     {
961       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
962       if (store == 0x0) return 0x0;
963       fIterator = store->CreateRegionalIterator();
964       if (fIterator == 0x0) return 0x0;
965       fCurrentIteratorType = kRegionalTriggerIterator;
966       return fIterator;
967     }
968     
969   case kTriggerTrackIterator:
970     {
971       AliMUONVTriggerTrackStore* store = TriggerTrackStore(fCurrentEvent);
972       if (store == 0x0) return 0x0;
973       fIterator = store->CreateIterator();
974       if (fIterator == 0x0) return 0x0;
975       fCurrentIteratorType = kTriggerTrackIterator;
976       return fIterator;
977     }
978     
979   default:
980     return 0x0;
981   }
982 }
983
984 //_____________________________________________________________________________
985 void AliMUONDataInterface::ResetIterator()
986 {
987 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
988 /// The iterator type and temporary data indicating the state of the iterator are
989 /// also reset.
990
991   if (fIterator != 0x0) delete fIterator;
992   fCurrentIteratorType = kNoIterator;
993   fCurrentIndex = fDataX = fDataY = -1;
994   fIterator = 0x0;
995 }
996
997 //_____________________________________________________________________________
998 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
999 {
1000 /// Counts the number of objects in the iterator and resets it.
1001 /// @return The number of objects in 'iter'.
1002
1003   if (iter == 0x0) return -1;
1004   Int_t count = 0;
1005   iter->Reset();
1006   while ( iter->Next() != 0x0 ) count++;
1007   iter->Reset();
1008   fCurrentIndex = -1;
1009   return count;
1010 }
1011
1012 //_____________________________________________________________________________
1013 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
1014 {
1015 /// Fetches the index'th object from the iterator counting the first object
1016 /// returned by iterator after it is reset as index == 0. The next object
1017 /// has index == 1 and so on where the last object returned by the iterator
1018 /// has index == N-1 where N = CountObjects(iter)
1019 /// This method will only reset the iterator if index is smaller than
1020 /// fCurrentIndex, which is used to track the iteration progress and is
1021 /// updated when a new object if returned by this method.
1022 /// @param iter  The iterator to fetch an object from.
1023 /// @param index The index number of the object to fetch in the range [0 .. N-1]
1024 ///        where N = CountObjects(iter)
1025
1026   if (index < 0)
1027   {
1028     AliError(Form("Index is out of bounds. Got a value of %d.", index));
1029     return 0x0;
1030   }
1031
1032   if (iter == 0x0) return 0x0;
1033   if (index <= fCurrentIndex)
1034   {
1035     iter->Reset();
1036     fCurrentIndex = -1;
1037   }
1038   
1039   TObject* object = 0x0;
1040   while (fCurrentIndex < index)
1041   {
1042     object = iter->Next();
1043     if (object == 0x0)
1044     {
1045       AliError(Form("Index is out of bounds. Got a value of %d.", index));
1046       iter->Reset();
1047       fCurrentIndex = -1;
1048       return 0x0;
1049     }
1050     fCurrentIndex++;
1051   }
1052   return object;
1053 }