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