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