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