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