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