]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONDataInterface.cxx
No effc++ warnings in RALICE
[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=kFALSE;
405       Bool_t yTrig=kFALSE;
406       
407       if ( locTrg->LoSdev()==1 && locTrg->LoDev()==0 && 
408            locTrg->LoStripX()==0) xTrig=kFALSE; // no trigger in X
409       else xTrig=kTRUE;                         // trigger in X
410       if (locTrg->LoTrigY()==1 && 
411           locTrg->LoStripY()==15 ) yTrig = kFALSE; // no trigger in Y
412       else yTrig = kTRUE;                          // trigger in Y
413       
414       if (xTrig && yTrig) 
415       { // fill ntuple if trigger in X and Y                    
416         tupleLoc.Fill(ievent,locTrg->LoCircuit(),
417                        locTrg->LoStripX(),
418                        locTrg->LoDev(),
419                        locTrg->LoStripY(),
420                        locTrg->LoLpt(),
421                        locTrg->LoHpt(),
422                        triggerCircuit.GetY11Pos(locTrg->LoCircuit(),locTrg->LoStripX()),
423                        triggerCircuit.GetY21Pos(locTrg->LoCircuit(),locTrg->LoStripX()+locTrg->LoDev()+1),
424                        triggerCircuit.GetX11Pos(locTrg->LoCircuit(),locTrg->LoStripY()));
425       }
426       tupleGlo.Fill(ievent,gloTrg->SingleLpt(),gloTrg->SingleHpt(),
427                      gloTrg->PairUnlikeLpt(),gloTrg->PairUnlikeHpt(),
428                      gloTrg->PairLikeLpt(),gloTrg->PairLikeHpt());
429     } // end of loop on local triggers
430   } // end of loop on events
431   
432   // print info and store ntuples
433   printf("\n");
434   printf("=============================================\n");
435   printf("================  SUMMARY  ==================\n");
436   printf("\n");
437   printf("Total number of events processed %d \n",nevents);
438   printf("\n");
439   printf(" Global Trigger output       Low pt  High pt\n");
440   printf(" number of Single           :\t");
441   printf("%i\t%i\t",sLowpt,sHighpt);
442   printf("\n");
443   printf(" number of UnlikeSign pair  :\t"); 
444   printf("%i\t%i\t",uSLowpt,uSHighpt);
445   printf("\n");
446   printf(" number of LikeSign pair    :\t");  
447   printf("%i\t%i\t",lSLowpt,lSHighpt);
448   printf("\n");
449   printf("=============================================\n");
450   fflush(stdout);    
451   
452   TFile myFile(fileNameOut, "RECREATE");
453   tupleGlo.Write();
454   tupleLoc.Write();
455   myFile.Close();
456 }
457
458 //_____________________________________________________________________________
459 Bool_t
460 AliMUONDataInterface::LoadEvent(Int_t event)
461 {
462   /// Load event if different from the current one.
463   /// Returns kFALSE on error and kTRUE if the event was loaded.
464   
465   assert( IsValid() );
466   
467   AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
468   if (fLoader->GetRunLoader()->GetEvent(event) == 0)
469   {
470     fCurrentEvent = event;
471     return kTRUE;
472   }
473   else
474     return kFALSE;
475 }
476
477 //______________________________________________________________________________
478 Int_t
479 AliMUONDataInterface::NumberOfEvents() const
480 {
481   /// Number of events in the current galice.root file we're attached to 
482   if (not IsValid()) return -1;
483   return fLoader->GetRunLoader()->GetNumberOfEvents();
484 }
485
486 //_____________________________________________________________________________
487 void
488 AliMUONDataInterface::Open(const char* filename)
489 {
490   /// Connect to a given galice.root file
491   
492   ResetStores();
493   
494   fCurrentEvent=-1;
495   
496   if ( fLoader != 0x0 ) 
497   {
498     delete fLoader->GetRunLoader();
499   }
500   
501   fLoader = 0x0;
502   
503   fIsValid = kTRUE;
504   
505   TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
506   
507   while (AliRunLoader::GetRunLoader(foldername) != 0x0) 
508   {
509     delete AliRunLoader::GetRunLoader(foldername);
510   }
511   
512   AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
513   if (runLoader == 0x0) 
514   {
515     AliError(Form("Cannot open file %s",filename));    
516     fIsValid = kFALSE;
517   }
518
519   runLoader->LoadHeader();
520   if ( ! runLoader->GetHeader() ) {
521     AliError("Cannot load header.");    
522     fIsValid = kFALSE;
523   }
524   else {
525     Int_t runNumber = runLoader->GetHeader()->GetRun();
526     AliCDBManager::Instance()->SetRun(runNumber);
527   }  
528   runLoader->UnloadHeader(); 
529
530   fLoader = runLoader->GetDetectorLoader("MUON");
531   if (fLoader == 0x0) 
532   {
533     AliError("Cannot get AliMUONLoader");
534     fIsValid = kFALSE;
535   }
536   
537   if (not IsValid())
538   {
539     AliError(Form("Could not access %s filename. Object is unuseable",filename));
540   }
541 }
542
543 //_____________________________________________________________________________
544 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
545 {
546 /// Loads all reconstructed data for the given event.
547
548   if (DigitStore(event) == 0x0) return kFALSE;
549   if (ClusterStore(event) == 0x0) return kFALSE;
550   if (TriggerStore(event) == 0x0) return kFALSE;
551   return kTRUE;
552 }
553
554 //_____________________________________________________________________________
555 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
556 {
557 /// Returns the number of digits to be found on a given detector element.
558 /// @param detElemId  The detector element ID number to search on.
559
560   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
561   return CountObjects(iter);
562 }
563
564 //_____________________________________________________________________________
565 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
566 {
567 /// Returns the a pointer to the index'th digit on the specified detector element.
568 /// @param detElemId  The detector element ID number to search on.
569 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
570 ///   where N = NumberOfDigits(detElemId)
571
572   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
573   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
574 }
575
576 //_____________________________________________________________________________
577 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
578 {
579 /// Returns the number of digits to be found on a specific chamber and cathode.
580 /// @param chamber  The chamber number in the range [0 .. 13].
581 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
582 ///   1 is the non-bending plane.
583
584   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
585   return CountObjects(iter);
586 }
587
588 //_____________________________________________________________________________
589 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
590 {
591 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
592 /// @param chamber  The chamber number in the range [0 .. 13].
593 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
594 ///   1 is the non-bending plane.
595 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
596 ///   where N = NumberOfDigits(chamber, cathode)
597
598   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
599   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
600 }
601
602 //_____________________________________________________________________________
603 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
604 {
605 /// Returns the number of reconstructed raw clusters on the specified chamber.
606 /// @param chamber  The chamber number in the range [0 .. 13].
607
608   TIterator* iter = GetIterator(kRawClusterIterator, chamber);
609   return CountObjects(iter);
610 }
611
612 //_____________________________________________________________________________
613 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
614 {
615 /// Returns a pointer to the index'th raw cluster on the specified chamber.
616 /// @param chamber  The chamber number in the range [0 .. 13].
617 /// @param index  The index number of the raw cluster to fetch in the range [0 .. N-1],
618 ///   where N = NumberOfRawClusters(chamber)
619
620   TIterator* iter = GetIterator(kRawClusterIterator, chamber);
621   return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
622 }
623
624 //_____________________________________________________________________________
625 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
626 {
627 /// Returns the number of reconstructed local trigger objects.
628
629   TIterator* iter = GetIterator(kLocalTriggerIterator);
630   return CountObjects(iter);
631 }
632
633 //_____________________________________________________________________________
634 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
635 {
636 /// Returns a pointer to the index'th local trigger object.
637 /// @param index  The index number of the local trigger object to fetch in the range [0 .. N-1],
638 ///   where N = NumberOfLocalTriggers()
639
640   TIterator* iter = GetIterator(kLocalTriggerIterator);
641   return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
642 }
643
644 //_____________________________________________________________________________
645 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
646 {
647 /// Returns the number of regional trigger objects reconstructed.
648
649   TIterator* iter = GetIterator(kRegionalTriggerIterator);
650   return CountObjects(iter);
651 }
652
653 //_____________________________________________________________________________
654 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
655 {
656 /// Returns a pointer to the index'th regional trigger object.
657 /// @param index  The index number of the regional trigger object to fetch in the range [0 .. N-1],
658 ///   where N = NumberOfRegionalTriggers()
659
660   TIterator* iter = GetIterator(kRegionalTriggerIterator);
661   return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
662 }
663
664 //_____________________________________________________________________________
665 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
666 {
667 /// Returns a pointer to the reconstructed global trigger object for the event.
668
669   AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
670   if (store == 0x0) return 0x0;
671   return store->Global();
672 }
673
674 //_____________________________________________________________________________
675 void AliMUONDataInterface::ResetStores()
676 {
677 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
678 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
679
680   ResetIterator();
681   if (fDigitStore != 0x0)
682   {
683     delete fDigitStore;
684     fDigitStore = 0x0;
685   }
686   if (fTriggerStore != 0x0)
687   {
688     delete fTriggerStore;
689     fTriggerStore = 0x0;
690   }
691   if (fClusterStore != 0x0)
692   {
693     delete fClusterStore;
694     fClusterStore = 0x0;
695   }
696 }
697
698 //_____________________________________________________________________________
699 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
700 {
701 /// Creates an appropriate iterator object and returns it.
702 /// If the iterator has already been created then that one is returned otherwise
703 /// a new object is created.
704 /// Depending on the value of 'type' the semantics of parameters x and y can change.
705 /// @param type  The type of iterator to create.
706 /// @param x  This is the detector element ID if type == kDigitIteratorByDetectorElement
707 ///           If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
708 ///           then this is the chamber number. In all other cases this parameter is
709 ///           ignored.
710 /// @param y  If type == kDigitIteratorByChamberAndCathode then this parameter is the
711 ///           cathode number. In all other cases this parameter is
712 ///           ignored.
713
714   if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
715         return fIterator;
716   
717   if (fCurrentEvent == -1)
718   {
719     AliError("No event was selected. Try first using GetEvent().");
720     return 0x0;
721   }
722   
723   ResetIterator();
724   
725   switch (type)
726   {
727   case kDigitIteratorByDetectorElement:
728     {
729       Int_t detElem = x;
730       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
731       if (store == 0x0) return 0x0;
732       fIterator = store->CreateIterator(detElem, detElem, 2);
733       if (fIterator == 0x0) return 0x0;
734       fCurrentIteratorType = kDigitIteratorByDetectorElement;
735       fDataX = detElem;
736       return fIterator;
737     }
738     
739   case kDigitIteratorByChamberAndCathode:
740     {
741       Int_t chamber = x;
742       Int_t cathode = y;
743       if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
744       {
745         AliError(Form(
746           "Must have give a chamber value in the range [0..%d], but got a value of: %d",
747           AliMpConstants::NofChambers() - 1,
748           chamber
749         ));
750         return 0x0;
751       }
752       if (cathode < 0 or 1 < cathode)
753       {
754         AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
755         return 0x0;
756       }
757       
758       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
759       if (store == 0x0) return 0x0;
760       AliMpIntPair pair = AliMpDEManager::GetDetElemIdRange(chamber);
761       fIterator = store->CreateIterator(pair.GetFirst(), pair.GetSecond(), cathode);
762       if (fIterator == 0x0) return 0x0;
763       fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
764       fDataX = chamber;
765       fDataY = cathode;
766       return fIterator;
767     }
768     
769   case kRawClusterIterator:
770     {
771       Int_t chamber = x;
772       AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
773       if (store == 0x0) return 0x0;
774       fIterator = store->CreateChamberIterator(chamber, chamber);
775       if (fIterator == 0x0) return 0x0;
776       fCurrentIteratorType = kRawClusterIterator;
777       fDataX = chamber;
778       return fIterator;
779     }
780     
781   case kLocalTriggerIterator:
782     {
783       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
784       if (store == 0x0) return 0x0;
785       fIterator = store->CreateLocalIterator();
786       if (fIterator == 0x0) return 0x0;
787       fCurrentIteratorType = kLocalTriggerIterator;
788       return fIterator;
789     }
790     
791   case kRegionalTriggerIterator:
792     {
793       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
794       if (store == 0x0) return 0x0;
795       fIterator = store->CreateRegionalIterator();
796       if (fIterator == 0x0) return 0x0;
797       fCurrentIteratorType = kRegionalTriggerIterator;
798       return fIterator;
799     }
800     
801   default:
802     return 0x0;
803   }
804 }
805
806 //_____________________________________________________________________________
807 void AliMUONDataInterface::ResetIterator()
808 {
809 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
810 /// The iterator type and temporary data indicating the state of the iterator are
811 /// also reset.
812
813   if (fIterator != 0x0) delete fIterator;
814   fCurrentIteratorType = kNoIterator;
815   fCurrentIndex = fDataX = fDataY = -1;
816   fIterator = 0x0;
817 }
818
819 //_____________________________________________________________________________
820 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
821 {
822 /// Counts the number of objects in the iterator and resets it.
823 /// @return The number of objects in 'iter'.
824
825   if (iter == 0x0) return -1;
826   Int_t count = 0;
827   iter->Reset();
828   while ( iter->Next() != 0x0 ) count++;
829   iter->Reset();
830   fCurrentIndex = -1;
831   return count;
832 }
833
834 //_____________________________________________________________________________
835 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
836 {
837 /// Fetches the index'th object from the iterator counting the first object
838 /// returned by iterator after it is reset as index == 0. The next object
839 /// has index == 1 and so on where the last object returned by the iterator
840 /// has index == N-1 where N = CountObjects(iter)
841 /// This method will only reset the iterator if index is smaller than
842 /// fCurrentIndex, which is used to track the iteration progress and is
843 /// updated when a new object if returned by this method.
844 /// @param iter  The iterator to fetch an object from.
845 /// @param index The index number of the object to fetch in the range [0 .. N-1]
846 ///        where N = CountObjects(iter)
847
848   if (index < 0)
849   {
850     AliError(Form("Index is out of bounds. Got a value of %d.", index));
851     return 0x0;
852   }
853
854   if (iter == 0x0) return 0x0;
855   if (index <= fCurrentIndex)
856   {
857     iter->Reset();
858     fCurrentIndex = -1;
859   }
860   
861   TObject* object = 0x0;
862   while (fCurrentIndex < index)
863   {
864     object = iter->Next();
865     if (object == 0x0)
866     {
867       AliError(Form("Index is out of bounds. Got a value of %d.", index));
868       iter->Reset();
869       fCurrentIndex = -1;
870       return 0x0;
871     }
872     fCurrentIndex++;
873   }
874   return object;
875 }